in reply to safely passing args through ssh

ssh takes a shell command.

# Passing <<echo>> <<$$>> executes <<echo $$>> $ ssh example.com echo '$$' 10920 # Passing <<echo>> <<'$$'>> executes <<echo '$$'>> $ ssh example.com echo ''\''$$'\''' $$ # Passing <<echo '$$'>> executes <<echo '$$'>> $ ssh example.com 'echo '\''$$'\''' $$

So you have to build a shell command.

sub text_to_shell_lit(_) { return $_[0] if $_[0] =~ /^[a-zA-Z0-9_\-]+\z/; my $s = $_[0]; $s =~ s/'/'\\''/g; return "'$s'"; } my $remote_cmd = join ' ', map text_to_shell_lit, perl => ( '-e' => $perl_code ); backticks(ssh => ( '--', $target, $remote_cmd ));

Replies are listed 'Best First'.
Re^2: safely passing args through ssh
by perl5ever (Pilgrim) on Jul 25, 2011 at 15:06 UTC
    I'm not sure this survives a double-ssh call:
    print backticks('ssh', 'localhost', '--', 'ssh', 'localhost', '--', +'argcount', text_to_shell_lit('a b c'));
    This prints 3 for me.

    As I mentioned in the original post, I was doubtful that backslash-escaping could solve the problem, but there still might be a way to do it.

      That doesn't look anything like what I wrote. I showed how to contruct a shell command to pass to ssh but you passed 5 arguments after the target, none of which a shell command.

      If you call ssh twice, you have two shell commands to build.

      sub text_to_shell_lit(_) { return $_[0] if $_[0] =~ /^[a-zA-Z0-9_\-]+\z/; my $s = $_[0]; $s =~ s/'/'\\''/g; return "'$s'"; } my $very_remote_cmd = join ' ', map text_to_shell_lit, argcount => ( 'a b c' ); my $remote_cmd = join ' ', map text_to_shell_lit, ssh => ( '--', $very_remote_target, $very_remote_cmd ); backticks(ssh => ( '--', $remote_target, $remote_cmd ));
        Well, then I guess you didn't solve the problem that I stated.