Передача переменной среды через SSH / цитирование в bash / sh / csh / tcsh
2645
Ole Tange
Я хочу передать переменную среды через 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 в качестве оболочки входа в систему):
Чтобы ответить на этот вопрос, ваше решение должно:
иметь возможность передавать переменную среды на удаленный сервер
не использовать SendEnv / AcceptEnv / PermitUserEnvironment
работать независимо от того, является ли исходная оболочка sh / bash / csh / tcsh
работать независимо от того, является ли оболочка назначения sh / bash / csh / tcsh
работать независимо от содержания переменной среды. В частности, он должен по крайней мере работать для: \ n * space '"? <>! $ \ И любой их комбинации.
Если вы можете найти лучший способ передачи переменной, чем заключить ее в кавычки, то это тоже хорошо.
Похоже, мы делаем твою домашнюю работу. Почему вы не можете использовать опции ssh SendEnv или AcceptEnv? Вот для чего они предназначены.
UtahJarhead 12 лет назад
0
Он должен использоваться для --env в GNU Parallel. GNU Parallel используется примерно 25000 пользователей. Многие из этих пользователей не имеют корневого доступа в системах, которые они используют (часто это вычислительные кластеры). Если бы AcceptEnv не требовал root-доступа, я бы согласился. Как вы можете видеть ниже, я нашел решение, которое работает для всех, кроме \ n.
Ole Tange 12 лет назад
0
Ах, это имеет смысл. Спасибо за разъяснения.
UtahJarhead 12 лет назад
0
2 ответа на вопрос
1
Ole Tange
I now have a working model for all characters except \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 . join(" && ", @qcsh) . q{ || } . join(" && ", @qbash) .q{;}); print shell_quote_scalar($Global::envvar);
0
Darth Android
Вы можете просто base64-кодировать переменную? Самый простой способ справиться с этим, вероятно, просто обработать данные как двоичные.
Возможно, вам придется возиться с цитатой в sshстроке, но в этом суть. Это должно удалить особенности оболочки в отношении цитирования, но может ввести некоторых с подкомандами (я не очень знаком с чем-то за пределами bash)
Неплохая идея. Хотя я, вероятно, не могу предположить, что base64 установлен (base64 является частью ядра GNU Coreutils и появился только в 2006 году - поэтому мы не можем предполагать, что он установлен в системах без GNU и в системах GNU до 2006 года). Однако я могу предположить, что установлена старая версия Perl, поэтому используйте (не) пакет с шаблоном "u *", что должно быть выполнимо.
Ole Tange 12 лет назад
0
UUEN кодированные строки включают *. ARGH! Но закодированный hex должен работать.
Ole Tange 12 лет назад
0
Я не могу найти способ заставить это работать: поскольку команда должна работать как с csh, так и с bash, мне нужно проверить ее. И как только я это сделаю, тогда * и? вызовет проблемы в csh. `echo setenv U`` perl -e '($ a = "212223c2a425262f28293d410a417b5b5d7d5e7e2a41") = ~ s /(..)/ chr hex $ 1 / например; напечатать $ a'`
Ole Tange 12 лет назад
0
@OleTange Доступен ли `openssl`? http://hints.macworld.com/article.php?story=20030721010526390
Darth Android 12 лет назад
0
Нету. Но даже если бы base64 был доступен, это не решило бы проблему: мне все еще нужно сделать eval, и именно этот шаг нарушает (t) csh, если переменная содержит * или? (Bash работает нормально, как и csh / tcsh, если переменная не содержит * или?).
Ole Tange 12 лет назад
0