通过SSH将变量传递给远程脚本

时间:2011-07-19 11:06:51

标签: linux bash shell ubuntu ssh

我通过SSH从本地服务器在远程服务器上运行脚本。首先使用SCP复制脚本,然后在传递一些参数时调用,如下所示:

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

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

这很好用,在远程服务器上,变量MYVAR1MYVAR2可以使用相应的值。

问题是这些脚本处于不断发展状态,每次重命名,添加或删除变量时都需要更改SSH命令。<​​/ p>

我正在寻找一种方法将所有本地环境变量传递给远程脚本(因为MYVAR1MYVAR2实际上是本地环境变量),这将解决SSH命令维护问题。< / p>

由于MYVAR1=1 \MYVAR1=1 \env命令输出后面的行,我尝试用实际命令替换它们,如下所示:

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

这似乎适用于“简单”env输出行(例如SHELL=/bin/bashLOGNAME=sysadmin),但是我会因更多“复杂”输出行而出错(例如{{1}这会产生诸如LS_COLORS=rs=0:di=01;34:ln=01;[...])之类的错误。我可以通过在运行SSH命令之前取消设置与这些复杂输出行相对应的变量来解决这些错误(例如-bash: 34:ln=01: command not found,然后unset LS_COLORS)但是我发现这个解决方案非常可靠。< / p>

问:有人知道如何通过SSH将所有本地环境变量传递给远程脚本吗?

PS:本地环境变量不是远程计算机so I cannot use this solution上可用的环境变量。

使用解决方案更新

我最后使用ssh [...]格式化从sedenv的{​​{1}}命令输出(并将所有行连接到1),这阻止bash解释一些输出为命令并修复我的问题。

VAR=VALUE

6 个答案:

答案 0 :(得分:7)

我碰巧阅读了与此无关的sshd_config手册页,找到了选项AcceptEnv

  

<强> AcceptEnv               指定客户端发送的环境变量   将会               复制到会话的环境中(7)。请参阅SendEnv in               ssh_config(5)用于配置客户端。注意   ENVI提取               只有协议2支持ronment传递。   变量是               由name指定,可能包含通配符   字符*' and?'。可以分离多个环境变量   通过               空格或分布在多个AcceptEnv指令中。   是               警告说可以使用一些环境变量   旁路               受限用户环境。出于这个原因,关心   应该               采用这个指令。默认不是   接受               任何环境变量。

也许您可以将其与AcceptEnv: *一起使用?我没有方便的sshd盒子,但试试看!

答案 1 :(得分:2)

问题是;标记了命令的结束。你必须逃脱它们:

尝试使用此命令:

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;的形式输出变量。这样做可以确保在执行命令之前,在远程主机上设置每个变量的相关性。

答案 2 :(得分:2)

您应该使用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"

答案 3 :(得分:1)

如何同时上传环境?

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"

答案 4 :(得分:1)

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);

如果您的环境变量包含引人注目的有趣内容,它就不会中断。

答案 5 :(得分:0)

此解决方案适合我。 假设您有两个参数或两个变量的脚本:

#!/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"

输出将是:

local
This is first params
And this is second
remote
This is first params
And this is second