Передача переменных в удаленный скрипт через SSH - PullRequest
5 голосов
/ 19 июля 2011

Я запускаю сценарии на удаленном сервере с локального сервера через SSH.Сценарий сначала копируется с использованием SCP, а затем вызывается при передаче следующих аргументов:

scp /path/to/script server.example.org:/another/path/

ssh server.example.org \
MYVAR1=1 \
MYVAR2=2 \
/another/path/script

Это прекрасно работает, и на удаленном сервере переменные MYVAR1 и MYVAR2доступны с соответствующим значением.

Проблема заключается в том, что эти сценарии находятся в постоянном развитии, что требует изменения команды SSH при каждом переименовании, добавлении или удалении переменной.

Iищу способ передачи всех локальных переменных среды в удаленный сценарий (поскольку MYVAR1 и MYVAR2 на самом деле являются локальными переменными среды), которые могли бы решить проблему обслуживания команды SSH.

, начиная с MYVAR1=1 \ и MYVAR1=1 \ - строки, которые следуют за выводом команды env. Я попытался заменить их действительной командой следующим образом:

ssh server.example.org \
`env`
/another/path/script

Это похоже на "простые" env строки вывода (например,SHELL=/bin/bash или LOGNAME=sysadmin), однако я получаю ошибки для более «сложных» выходных строк (например, LS_COLORS=rs=0:di=01;34:ln=01;[...], который дает ошибки, такие как -bash: 34:ln=01: command not found).Я могу избавиться от этих ошибок, сбросив переменные, соответствующие этим сложным выходным строкам, перед запуском команды SSH (например, unset LS_COLORS, затем ssh [...]), однако я не считаю это решение очень надежным.

В: Кто-нибудь знает, как передать все локальные переменные среды в удаленный скрипт через SSH?

PS: локальные переменные среды не являются переменными среды, доступными на удаленной машине поэтому я не могу использовать это решение .

Обновление с решением

Я прекратил использовать sed для форматирования вывода команды env из VAR=VALUEв VAR="VALUE" (и объединение всех строк в 1), что не позволяет bash интерпретировать некоторые выходные данные как команды и исправляет мою проблему.

ssh server.example.org \
`env | sed 's/\([^=]*\)=\(.*\)/\1="\2"/' | tr '\n' ' '` \
"/another/path/script"

Ответы [ 6 ]

7 голосов
/ 19 июля 2011

Я случайно прочитал справочную страницу sshd_config, не связанную с этим, и нашел параметр AcceptEnv:

AcceptEnv Указывает, какие переменные среды будут отправлены клиентом.скопированы в среду сеанса (7).См. SendEnv в ssh_config (5), чтобы узнать, как настроить клиент.Обратите внимание, что передача среды поддерживается только для протокола 2. Переменные указываются по имени, которое может содержать символы подстановки *' and? '.Несколько переменных среды могут быть разделены пробелами или распределены по нескольким директивам AcceptEnv.Имейте в виду, что некоторые переменные среды могут использоваться для обхода ограниченных пользовательских сред.По этой причине следует соблюдать осторожность при использовании этой директивы.По умолчанию переменные среды не принимаются.

Может быть, вы могли бы использовать это с AcceptEnv: *?У меня нет коробки с sshd под рукой, но попробуйте!

2 голосов
/ 25 августа 2011

Вы должны использовать set вместо env.

Из руководства по bash:

Без параметров имя и значение каждой переменной оболочки отображаются в видеформат, который можно использовать в качестве входных данных для установки или сброса текущих установленных переменных.

Это решит все ваши проблемы с запятой и обратной косой чертой.есть переменные, которые вы не хотите отправлять, вы можете отфильтровать их следующим образом:

set | grep -v "DONT_NEED" > environment

Вы также можете обновить ~/.bash_profile в удаленной системе, чтобы запустить скрипт среды при входе в системучтобы вам не пришлось явно запускать скрипт среды:

ssh server.example.org "/another/path/script"
2 голосов
/ 19 июля 2011

Проблема в том, что ; отмечает конец вашей команды.Вы должны экранировать их:

Попробуйте выполнить эту команду:

env | sed 's/;/\\;/g'

Обновление : я протестировал команду с удаленного хоста, и она сработала для меня с помощью этой команды:

var1='something;using semicolons;'
ssh hostname "`env | sed 's/;/\\\\;/g' | sed 's/.*/set &\;/g'` echo \"$var1\""

Я дважды экранирую ; whit \\\\; и затем использую другую подстановку sed для вывода переменных в виде set name=value;.Благодаря этому перед выполнением команды все переменные будут установлены на удаленном хосте.

1 голос
/ 20 июля 2011

Perl на помощь:

#!/usr/bin/perl

use strict;
use warnings;

use Net::OpenSSH;
use Getopt::Long;

my $usage = "Usage:\n  $0 --env=FOO --env=BAR ... [user\@]host command args\n\n";

my @envs;
GetOptions("env=s" => \@envs)
    or die $usage;

my $host = shift @ARGV;
die $usage unless defined $host and @ARGV;

my $ssh = Net::OpenSSH->new($host);
$ssh->error and die "Unable to connect to remote host: " . $ssh->error;

my @cmds;
for my $env (@envs) {
    next unless defined $ENV{$env};
    push @cmds, "export " . $ssh->shell_quote($env) .'='.$ssh->shell_quote($ENV{$env})
}

my $cmd = join('&&', @cmds, '('. join(' ', @ARGV) .')');
warn "remote command: $cmd\n";
$ssh->system($cmd);

И он не сломается, если переменные вашей среды содержат забавные вещи в кавычках.

1 голос
/ 19 июля 2011

Как насчет загрузки среды одновременно?

scp /path/to/script server.example.org:/another/path/
env > environment
scp environment server.example.org:/another/path
ssh server.example.org "source environment; /another/path/script"
0 голосов
/ 14 апреля 2017

Это решение хорошо работает для меня.Предположим, у вас есть скрипт, который принимает два параметра или две переменные:

#!/bin/sh
echo "local"
echo "$1"
echo "$2"
/usr/bin/ssh root@192.168.1.2 "/path/test.sh \"$1\" \"$2\";"

и скрипт test.sh для 192.168.1.2:

#!/bin/bash
echo "remote"
echo "$1"
echo "$2"

Вывод будет:

local
This is first params
And this is second
remote
This is first params
And this is second
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...