sshkit
sshkit copied to clipboard
improve command map combined with prefix
It is valid use case to set both command map and prefix. In case of using different binary, the map should still be active and prefixed.
Includes and closes #310.
Will squash the commits when we agree that it makes sense.
It changes prefix to generate: bundle exec /usr/bin/env rake
instead of bundle exec rake
.
Would that be a breaking change?
I think this could break capistrano-rbenv. It adds the prefix $HOME/.rbenv/bin/rbenv exec
, and this would happen:
$HOME/.rbenv/bin/rbenv exec /usr/bin/env rake
rbenv: /usr/bin/env: command not found
@mattbrictson will check, thanks!
I'd expect rbenv exec
to behave like bundle exec
. Running any executable file with different environment. https://github.com/rbenv/rbenv/blob/a95ccd09a2c7cff435d915756abd5a2fe096fb9d/libexec/rbenv-exec looks like does exactly that, just prepares environment and calls exec.
I think running anything in /usr/bin/env
should be harmless.
So did we think we would merge this? This would also solve #299 which I'd be glad of, reading the notes here from you both it looks like the rbenv
issue was not really an issue?
I believe rbenv exec
is still a problem. Last I heard, @mikz was going to look into it some more.
@mattbrictson the example in https://github.com/capistrano/sshkit/pull/311#issuecomment-167902320 should fail also locally, right?
$ rbenv exec /usr/bin/env ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]
Works just fine for me.
We are using this patch in production for few weeks and successfully migrated to ruby 2.2 with this.
Rebased this to be mergeable again.
@mattbrictson I really don't have any server with rbenv. If you have any, could you try to do a deploy with this? I tried those commands locally and all works. From all the source code, it should be just fine. Wrapping a command in /usr/bin/env
, rbenv exec
or bundle exec
does the same thing. Just adds environment and execs that command. All those can be chained together as they just modify the env.
I'll see if I can check now.
Unfortunately it doesn't work in my local environment (OS X).
$ rbenv exec /usr/bin/env ruby -v
rbenv: /usr/bin/env: command not found
$ rbenv --version
rbenv 1.0.0
$ bash --version
GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin14.5.0)
Just to prove it works without the rbenv exec
part:
$ /usr/bin/env ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin14]
@mattbrictson that is so weird. It works for me. Also rbenv 1.0.0. Both in zsh and bash.
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
zsh 5.0.8 (x86_64-apple-darwin15.0)
I edited by /usr/local/Cellar/rbenv/1.0.0/libexec/rbenv-exec
and added there echo at the line before the exec and here is output for some commands i tried:
$ rbenv exec ruby -v ruby-2.3.0
exec -a ruby /Users/mikz/.rvm/rubies/ruby-2.3.0/bin/ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]
$ rbenv exec bash --version ruby-2.3.0
exec -a bash /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
$ rbenv exec env bash --version ruby-2.3.0
exec -a env /usr/bin/env bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
$ rbenv exec /usr/bin/env bash --version ruby-2.3.0
exec -a /usr/bin/env /usr/bin/env bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
I really don't see how that could fail. Could you also try running:
exec -a /usr/bin/env /usr/bin/env bash --version
exec /usr/bin/env bash --version
exec -a /usr/bin/env /usr/bin/env ruby --version
I have no idea how to reproduce this. That really should not happen AFAIK.
Well, clearly something strange is going on. My own OS X machine fails (rbenv installed via Homebrew), and other Ubuntu VMs that I have also fail (rbenv installed via Git clone). However, just now I provisioned a brand new Ubuntu 14.04 VM, installed rbenv, and rbenv exec
works fine there.
Perhaps it is a certain rbenv plugin that is causing issues, but I'm grasping at straws here. I'll try to figure it out.
I've narrowed it down: rbenv fails and prints command not found
on when it reaches this line: https://github.com/rbenv/rbenv/blob/e851250da66307a2584218b555068c941b493d44/libexec/rbenv-exec#L33
So: rbenv which /usr/bin/env
fails for you? What about rbenv which env
?
Could you try to run it with RBENV_DEBUG=1
?
Internally it is using command
like: command -v /usr/bin/env
(no message, just error code).
There are some script inclusions, that could affect it. It is hard to help when I can't make it fail.
edit: it looks like it has to be there: https://github.com/rbenv/rbenv/blob/e851250da66307a2584218b555068c941b493d44/libexec/rbenv-which#L52-L58
OK, if you look here: https://github.com/rbenv/rbenv/blob/e851250da66307a2584218b555068c941b493d44/libexec/rbenv-which#L38-L43
Then you'll see that rbenv-which
only searches the PATH if the current version is system
. Otherwise rbenv will search the bin directory of the current Ruby version, which of course doesn't have a binary named env
or bash
.
Example:
$ rbenv version
2.3.0 (set by /Users/mbrictson/.rbenv/version)
$ rbenv which /usr/bin/env
rbenv: /usr/bin/env: command not found
$ rbenv which env
rbenv: env: command not found
But if I switch to system
, then:
$ rbenv shell system
$ rbenv which /usr/bin/env
/usr/bin/env
$ rbenv which env
/usr/bin/env
Long story short, it only works if you don't have a default version set (and are therefore using the system version).
So. You cannot run ANY command that is not provided by ruby, via rbenv exec
? Wow.
Ok. Guess that is not going away no matter how wrong it is.
Lets figure out a way to disable this in the capistrano-rbenv plugin? Would you think that would be the right place to do so?
Honestly I'm not sure how to approach this. I don't use capistrano-rbenv in production, so I'm probably not a good person to give advice.
But to recap: my understanding is that capistrano-rbenv prefixes known Ruby binaries (e.g. rake, bundler) with rbenv exec
. If these are not mapped, then SSHKit's default map comes into play, which is to add /usr/bin/env
. And so (with this PR) you end up with rbenv exec /usr/bin/env rake
, which fails.
There isn't really an SSHKit API to disable the default env
mapping, except to add a new mapping. So I suppose capistrano-rbenv could add a "noop" mapping for the known Ruby binaries. But then that would clobber any user-provided mappings.
I don't see a way out. What's your take?