3

Я хочу передать переменную среды через SSH.

"Правильный" способ - использовать SendEnv/~/.ssh/environment , но для этого требуется, чтобы сервер поддерживал AcceptEnv или PermitUserEnvironment, чего в моем случае нет.

Поэтому вместо этого я думаю установить переменную на удаленном сайте следующим образом:

FOO=val
export FOO
ssh server export FOO=$FOO'; do_stuff_which_uses_FOO'

Эта часть проста. Я хочу универсальное решение, поэтому независимо от содержания $ FOO оно будет работать. Например

FOO="  '\""
export FOO
QFOO=`quote "$FOO"` # quote will return "\ \ \'\\\""
export QFOO
ssh server export FOO=$QFOO'; do_stuff_which_uses_FOO'

Это работает независимо от того, является ли отправляющая или получающая оболочка sh или bash.

Тем не менее, мне также нужно, чтобы он работал для csh/tcsh. И я не буду знать заранее, на какой оболочке работает принимающая сторона. Это означает, что мне нужно написать код, который будет работать как в /bin /sh, так и в /bin /csh.

До сих пор мне удалось заставить его работать на sh/bash:

ssh server // followed by the below quoted
eval `echo $SHELL | grep -E "/(t)?csh" > /dev/null && echo setenv FOO \\\ \\\ \\\\\'\\\\\" || echo export FOO=\\\ \\\ \\\\\'\\\\\";` ; echo "$FOO"

Я также могу заставить его работать для csh/tcsh (у пользователя csh есть csh в качестве оболочки входа в систему):

ssh csh@server // followed by the below quoted
eval `echo $SHELL | grep -E "/(t)?csh" > /dev/null && echo setenv FOO \\\ \\\ \\\\\'\\\\\" || echo export FOO=\\\ \\\ \\\\\'\\\\\";` ; echo "$FOO"

Если $ FOO это * или? он отлично работает с BASH:

ssh server eval\ \`echo\ \$SHELL\ \|\ grep\ -E\ \"/\(t\)\?csh\"\ \>\ /dev/null\ \&\&\ echo\ setenv\ FOO\ \\\\\\\\\\\*\\\;\ \|\|\ echo\ export\ FOO=\\\\\\\\\\\*\\\;\`\;echo\ \"\$FOO\"\ a;

Но это не с Csh:

ssh csh@server eval\ \`echo\ \$SHELL\ \|\ grep\ -E\ \"/\(t\)\?csh\"\ \>\ /dev/null\ \&\&\ echo\ setenv\ FOO\ \\\\\\\\\\\*\\\;\ \|\|\ echo\ export\ FOO=\\\\\\\\\\\*\\\;\`\;echo\ \"\$FOO\"\ a;
No match.
FOO: Undefined variable.

Кажется * а? отказаться от цитирования.

Чтобы ответить на этот вопрос, ваше решение должно:

  • иметь возможность передавать переменную среды на удаленный сервер
  • не использовать SendEnv/AcceptEnv/PermitUserEnvironment
  • работать независимо от того, является ли исходная оболочка sh/bash/csh/tcsh
  • работать независимо от того, является ли оболочка назначения sh/bash/csh/tcsh
  • работать независимо от содержания переменной среды. В частности, это должно по крайней мере работать для: \n * пробел '"? <>! $ \ и любая их комбинация.

Если вы можете найти лучший способ передачи переменной, чем заключить ее в кавычки, то это тоже хорошо.

2 ответа2

1

Теперь у меня есть рабочая модель для всех символов, кроме \n:

sub shell_quote_scalar {
    # Quote the string so shell will not expand any special chars
    # Returns:
    #   string quoted with \ as needed by the shell
    my $a = shift;
    $a =~ s/([\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\*\>\<\~\|\; \"\!\$\&\'\202-\377])/\\$1/g;
    $a =~ s/[\n]/'\n'/g; # filenames with '\n' is quoted using \'
    return $a;
}

sub env_quote {
    my $v = shift;
    $v =~ s/([ \n\&\<\>\(\)\;\'\{\}\t\"\$\`\*\174\!\?\~])/\\$1/g;
    return $v;
}

my @qcsh = map { my $a=$_; "setenv $a " . env_quote($ENV{$a})  } @vars;
my @qbash = map { my $a=$_; "export $a=" . env_quote($ENV{$a}) } @vars;

$Global::envvar =
    join"",
    (q{echo $SHELL | grep -E "/t?csh" > /dev/null && }
     . join(" && ", @qcsh)
     . q{ || }
     . join(" && ", @qbash)
     .q{;});

print shell_quote_scalar($Global::envvar);
0

Вы можете просто base64-кодировать переменную? Самый простой способ справиться с этим, вероятно, просто обработать данные как двоичные.

export QFOO=`echo $FOO | base64 --wrap=0`
ssh server "export FOO=`echo \"$QFOO\" | base64 --decode --wrap=0`; <command>"

Возможно, вам придется возиться с цитатами в строке ssh , но в этом суть. Это должно удалить специфику оболочки в отношении цитирования, но может ввести некоторые с подкомандами (я не очень знаком с чем-либо, кроме bash)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .