Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Exports added by :with are ineffective when :user is specified

Open
#490 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
48/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
ruby
Domain
devops

Research direction

Start by locating the with and user builder methods shown in the issue and inspect how they compose the generated shell command when both options are used. The change is done when the with builder does not add an export subshell for a user command, while the user builder still supplies the environment variables.

Written by the indexing model from the issue text.

Description

When a command is mapped, (:should_map?), both :with and :user are invoked.

In both builder methods, the environment variables specified are intended to be inherited by the subshell.

Say that we have the env var MYVAR=myvar, and the command mycommand, which needs to be run as the user myuser. The relevant builder methods are:

    def with(&_block)
      env_string = environment_string
      return yield if env_string.empty?
      "( export #{env_string} ; #{yield} )"
    end

    def user(&_block)
      return yield unless options[:user]
      env_string = environment_string
      "sudo -u #{options[:user].to_s.shellescape} #{env_string + " " unless env_string.empty?}-- sh -c #{yield.shellescape}"
    end

this will generate something like:

( export MYVAR=myvar ; sudo -u myuser MYVAR=myvar -- sh -c command )

The problem is that the export is ineffective, because exports are not inherited by the sudo subshell.

While this is harmless, it clutters the generated commands, and it's also semantically incorrect (because it's ineffective) and confusing.

This could be avoided by just yielding the the builder block if options[:user] is set:

    def with(&_block)
>      # Exports are ineffective on non-login (sudo) shells; in this case, the :user builder takes
>      # care of setting them.
>      return yield if options[:user]
      env_string = environment_string
      return yield if env_string.empty?
      "( export #{env_string} ; #{yield} )"
    end

This makes the (internal) commands output more readable (and understandable). While this has no effect on the end users, it helps understanding those who approach Capistrano/Sshkit development (at least, it did it for me 😬).

If this is approved (either in this form or another), I can easily open a PR.

Dominant language
Ruby
Stars
1.2k
Forks
257
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from capistrano/sshkit

All issues in capistrano/sshkit

Similar issues

More Ruby issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.