我试图远程执行此脚本:
perl -i -pe 's/nginx-cache\K(\d+)/ ++($n = $1) /e; s/MYSITE\K(\w+)/ ++($n = $1) /e;' $SITENAME
使用以下解决方案:
ssh -T root@$IPSRV <<EOI
perl -i -pe 's/nginx-cache\K(\d+)/ ++($n = $1) /e; s/MYSITE\K(\w+)/ ++($n = $1) /e;' /etc/nginx/sites-available/$SITENAME"
exit
EOI
我也试过没有&#34; -T&#34; ssh的选项
ssh root@$IPSRV "
> perl -i -pe 's/nginx-cache\K(\d+)/ ++($n = $1) /e; s/MYSITE\K(\w+)/ ++($n = $1) /e;' /etc/nginx/sites-available/$SITENAME"
但不幸的是它不起作用:
syntax error at -e line 1, near "( ="
syntax error at -e line 1, near "( ="
Execution of -e aborted due to compilation errors.
有人可以建议我远程运行此命令的解决方案吗? 提前谢谢!
请注意,$SITENAME
是本地计算机上的变量。
[编辑]
根据@ ikegami的回答,我取得了一些进展。 我试过了
root@$IPSRV 'perl -i -pe'\''s/nginx-cache\K(\d+)/ ++($n = $1) /e; s/MYSITE\K(\w+)/ ++($n = $1) /e;'\'' /etc/nginx/sites-available/"$SITENAME"'
root@192.168.1.100's password:
Can't do in place edit: /etc/nginx/sites-available/ is not a regular file.
我认为这与$ SITENAME变量的缺失替换有关。
要记住的另一个重要事项是在ssh root @ IPSRV之后使用单引号 - 它应该用引号替换,因为我在脚本中有其他变量,如果我使用单引号它们不会被翻译。 例如:
ssh root@$IPSRV "mkdir $TESTDIR
cp /tmp/file $TESTDIR"
这样可行,但如果我尝试使用单引号:
ssh root@$IPSRV 'mkdir $TESTDIR
cp /tmp/file $TESTDIR'
它没有。因此,如果运行perl替换的唯一方法是&#39; perl -i -pe&#39;&#39;&#39;&#39;&#39;&#39;&#39;
,我还必须考虑这个方面。谢谢!
答案 0 :(得分:5)
不正确的逃避。
ssh root@$IPSRV "...++($n = $1)..."
将...++( = )...
传递给远程主机。与here-doc版本相同。 (here-doc版本也有一个流浪的引用。)
处理多个转义级别很复杂,所以让我们以编程方式进行转义。这也允许我们传递变量中的值,因为它们需要转换为shell文字。
quote() {
prefix=''
for p in "$@" ; do
printf "$prefix"\'
printf %s "$p" | sed "s/'/'\\\\''/g"
printf \'
prefix=' '
done
}
ssh root@$IPSRV "$( quote perl -i -pe'...' "$SITENAME" )"
或
quote() {
perl -MString::ShellQuote=shell_quote -e'print(shell_quote(@ARGV))' "$@"
}
ssh root@$IPSRV "$( quote perl -i -pe'...' "$SITENAME" )"
如果它对其他人有帮助,下面将介绍如何使用远程机器的$SITENAME
var:
quote() {
prefix=''
for p in "$@" ; do
printf "$prefix"\'
printf %s "$p" | sed "s/'/'\\\\''/g"
printf \'
prefix=' '
done
}
ssh root@$IPSRV "$( quote perl -i -pe'...' )"' "$SITENAME"'
或
quote() {
perl -MString::ShellQuote=shell_quote -e'print(shell_quote(@ARGV))' "$@"
}
ssh root@$IPSRV "$( quote perl -i -pe'...' )"' "$SITENAME"'
或
ssh localhost sh <<'EOI' # Notice the quotes around the token.
perl -i -pe'...' "$SITENAME"
EOI
或者,因为它不需要任何局部变量,所以您可以轻松地手动完成。使用远程命令,将每个'
替换为'\''
,然后用引号括起整个。
远程命令:
perl -i -pe'...' "$SITENAME"
本地命令:
ssh root@$IPSRV 'perl -i -pe'\''...'\'' "$SITENAME"'
答案 1 :(得分:0)
手工引用很难发生错误。让Perl为您完成所有工作:
use Net::OpenSSH;
my $one_liner = <<'EOOL';
s/nginx-cache\K(\d+)/ ++($n = $1) /e; s/MYSITE\K(\w+)/ ++($n = $1) /e
EOOL
my $ssh = Net::OpenSSH->new("root\@$ENV{IPSRV}");
$ssh->system('perl', '-i', '-pe', $one_liner, $ENV{SITENAME});
$ssh->die_on_error;
不要忘记export
$IPSRV
和$SITENAME
。
答案 2 :(得分:0)
经过多次尝试后我才开始工作! ; - ))
问题与在将所有这些发送到远程SSH之前尝试扩展$ n或$ 1环境变量的shell有关。在远程端脚本变成:
perl -i -pe 's/nginx-cache\K(\d+)/ ++( = ) /e; s/MYSITE\K(\w+)/ ++( = ) /e;'
在“(=)”位置产生错误。 只需将它们转义为\ $ n就不会发送这些字符串:
perl -i -pe 's/nginx-cache\\K(\\d+)/ ++(\$n = \$1) /e; s/MYSITE\\K(\\w+)/ ++(\$n = \$1) /e;' $SITENAME
所以,完整的答案:
ssh root@IPSRV "
first command
second command
perl -i -pe 's/nginx-cache\\K(\\d+)/ ++(\$n = \$1) /e; s/MYSITE\\K(\\w+)/ ++(\$n = \$1) /e;' $SITENAME
"
感谢任何人指出我正确的方向!