sshkit
sshkit copied to clipboard
support commands/users/groups/directories with spaces or other shell characters
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
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
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)
https://github.com/capistrano/sshkit/pull/452 for just the sprintf change
/cc @leehambley since your name is all over command.rb :D
https://github.com/capistrano/sshkit/pull/453 for just the things I'd consider bugfixes
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. 👍