[英]Pass variables to remote script through SSH
我正在通过 SSH 从本地服务器在远程服务器上运行脚本。 该脚本首先使用 SCP 进行复制,然后在传递一些 arguments 时调用,如下所示:
scp /path/to/script server.example.org:/another/path/
ssh server.example.org \
MYVAR1=1 \
MYVAR2=2 \
/another/path/script
这工作正常,在远程服务器上,变量MYVAR1
和MYVAR2
可以使用它们对应的值。
问题是这些脚本在不断开发中,每次重命名、添加或删除变量时都需要更改 SSH 命令。
我正在寻找一种将所有本地环境变量传递给远程脚本的方法(因为MYVAR1
和MYVAR2
实际上是本地环境变量),这将解决 SSH 命令维护问题。
由于MYVAR1=1 \
和MYVAR1=1 \
是遵循env
命令 output 的行,因此我尝试用实际命令替换它们,如下所示:
ssh server.example.org \
`env`
/another/path/script
这似乎适用于“简单”环境env
行(例如SHELL=/bin/bash
或LOGNAME=sysadmin
),但是对于更“复杂”的 output 行(例如LS_COLORS=rs=0:di=01;34:ln=01;[...]
会给出诸如-bash: 34:ln=01: command not found
之类的错误)。 我可以通过在运行 SSH 命令之前取消设置与那些复杂的 output 行相对应的变量来消除这些错误(例如unset LS_COLORS
,然后取消设置 Z1787D7646304C5D987CF4E64A3978A050AZ 命令,然后ssh [...]
非常可靠的解决方案)。
问:有人知道如何通过 SSH 将所有本地环境变量传递给远程脚本吗?
PS:本地环境变量不是远程机器上可用的环境变量, 所以我不能使用这个解决方案。
更新解决方案
I ended using sed
to format the env
command output from VAR=VALUE
to VAR="VALUE"
(and concatenating all lines in to 1) which prevents bash from interpreting some of the output as commands and fixes my problem.
ssh server.example.org \
`env | sed 's/\([^=]*\)=\(.*\)/\1="\2"/' | tr '\n' ' '` \
"/another/path/script"
我碰巧阅读了与此无关的sshd_config
手册页,并找到了选项AcceptEnv
:
AcceptEnv指定客户端发送的环境变量将被复制到会话的 environ(7) 中。 有关如何配置客户端,请参阅 ssh_config(5) 中的 SendEnv。 请注意,仅协议 2 支持环境传递。变量由名称指定,其中可能包含通配符
*' and
?'。 多个环境变量可以由空格分隔或分布在多个 AcceptEnv 指令中。 请注意,某些环境变量可用于绕过受限用户环境。 因此,在使用该指令时应谨慎。 默认是不接受任何环境变量。
也许您可以将其与AcceptEnv: *
一起使用? 我手边没有带 sshd 的盒子,但试试看吧!
问题是;
标记命令的结束。 你必须逃避它们:
试试这个命令:
env | sed 's/;/\\;/g'
更新:我在远程主机上测试了该命令,它使用以下命令对我有用:
var1='something;using semicolons;'
ssh hostname "`env | sed 's/;/\\\\;/g' | sed 's/.*/set &\;/g'` echo \"$var1\""
我双重逃脱;
丝毫\\\\;
然后我使用另一个 sed 替换 output 变量,形式为set name=value;
. 这样做可确保在执行命令之前在远程主机上正确设置每个变量。
您应该使用set
而不是env
。
从 bash 手册:
在没有选项的情况下,每个 shell 变量的名称和值都以可重复用作设置或重置当前设置变量的输入的格式显示。
这将解决您所有的分号和反斜杠问题。
scp /path/to/script server.example.org:/another/path/
set > environment
scp environment server.example.org:/another/path/
ssh server.example.org "source environment; /another/path/script"
如果您不想发送任何变量,可以使用以下内容将它们过滤掉:
set | grep -v "DONT_NEED" > environment
您还可以更新远程系统上的~/.bash_profile
以在登录时运行环境脚本,这样您就不必显式运行环境脚本:
ssh server.example.org "/another/path/script"
同时上传环境怎么样?
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"
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);
如果您的环境变量包含有趣的东西作为引号,它不会中断。
这个解决方案对我很有效。 假设您有一个带有两个参数或两个变量的脚本:
#!/bin/sh
echo "local"
echo "$1"
echo "$2"
/usr/bin/ssh root@192.168.1.2 "/path/test.sh \"$1\" \"$2\";"
并在 192.168.1.2 上编写 test.sh 脚本:
#!/bin/bash
echo "remote"
echo "$1"
echo "$2"
Output 将是:
local
This is first params
And this is second
remote
This is first params
And this is second
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.