sshkit icon indicating copy to clipboard operation
sshkit copied to clipboard

support commands/users/groups/directories with spaces or other shell characters

Open grosser opened this issue 6 years ago • 6 comments

host = SSHKit::Host.new(hostname: "localhost")
SSHKit::Coordinator.new([host]).each { capture "sh", "-c", "touch 1 && echo 1" }.first.value

this should execute "sh -c touch\ 1 &&\ echo\ 1" and not sh -c touch 1 and echo 1 ... same issue for directories/users/groups ... also making user and group use the same form of escaping ... I'm pretty sure nohup should also do sh -c to avoid funky issues

/fyi @eatwithforks @adammw @jonmoter this is why we saw crazy issues :D

... cap-devs, please let me know if this looks correct, or if I understood something wrong

grosser avatar Feb 18 '19 23:02 grosser

This is a breaking change to the behavior of SSHKit. I won't be able to accept this PR as is.

However there are still improvements here that I can definitely get behind, if you'd like to split them off into another PR. For example I like replacing the sprintf("...%s", yield) statements with the much more readable "...#{yield}" template strings.

Also, how about adding to the documentation instead of changing the behavior? For example the docs could offer advice about using .shellescape when dealing with strings that are not shell-safe. Like:

capture "sh", "-c", "touch 1 && echo 1".shellescape

mattbrictson avatar Feb 19 '19 00:02 mattbrictson

Afaik ruby convention is that passing arrays to system calls is supposed to escape them, that's how system/exec/sh/IO.popen etc work. Not doing that is also violating the users expectation:

foo "bar baz" is call the binary foo with the argument "bar baz" and not call the binary foo with the argument "bar" and "baz"

Agreed that this is not a simple patch, and will need a minor or major bump, but I think it's the obvious/expected way it should work, otherwise it's just "random bugs" since things like adding a user/group will suddenly change what the command means. (also user already had a poor mans escaping for the wrapped command, so at least this can be seen as a bugfix release)

grosser avatar Feb 19 '19 00:02 grosser

https://github.com/capistrano/sshkit/pull/452 for just the sprintf change

grosser avatar Feb 19 '19 00:02 grosser

/cc @leehambley since your name is all over command.rb :D

grosser avatar Feb 19 '19 00:02 grosser

https://github.com/capistrano/sshkit/pull/453 for just the things I'd consider bugfixes

grosser avatar Feb 19 '19 00:02 grosser

Afaik ruby convention is that passing arrays to system calls is supposed to escape them, that's how system/exec/sh/IO.popen etc work

I don't think the comparison holds up exactly. In Ruby's system, for example, a string is interpreted by a shell, whereas an array of arguments is executed directly, without a shell. In SSHKit, commands are always executed by a shell.

Arguments about "correctness" aside, SSHKit is a mature library (it has been >5 years since 1.0.0) and as a maintainer I personally place more value on keeping existing users happy and free from surprising changes. I will defer to @leehambley since he probably has more experience in this particular area.

Thanks for splitting up into separate PRs. 👍

mattbrictson avatar Feb 19 '19 01:02 mattbrictson