sshkit icon indicating copy to clipboard operation
sshkit copied to clipboard

improve command map combined with prefix

Open mikz opened this issue 9 years ago • 16 comments

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?

mikz avatar Dec 28 '15 15:12 mikz

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 avatar Dec 29 '15 23:12 mattbrictson

@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.

mikz avatar Dec 30 '15 00:12 mikz

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?

leehambley avatar Feb 21 '16 18:02 leehambley

I believe rbenv exec is still a problem. Last I heard, @mikz was going to look into it some more.

mattbrictson avatar Feb 22 '16 16:02 mattbrictson

@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.

mikz avatar Feb 24 '16 09:02 mikz

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.

mikz avatar Feb 24 '16 09:02 mikz

I'll see if I can check now.

leehambley avatar Feb 24 '16 10:02 leehambley

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)

mattbrictson avatar Feb 24 '16 18:02 mattbrictson

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 avatar Feb 24 '16 18:02 mattbrictson

@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.

mikz avatar Feb 24 '16 19:02 mikz

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.

mattbrictson avatar Feb 24 '16 19:02 mattbrictson

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

mattbrictson avatar Feb 24 '16 22:02 mattbrictson

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

mikz avatar Feb 24 '16 22:02 mikz

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).

mattbrictson avatar Feb 24 '16 23:02 mattbrictson

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?

mikz avatar Feb 24 '16 23:02 mikz

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?

mattbrictson avatar Feb 25 '16 00:02 mattbrictson