我正在尝试运行一个SSH命令,该命令将调用远程计算机上的脚本,该脚本将一些Lua代码写入文件。
我有这个在bash下执行的脚本命令:
ssh bob writelua.sh '{version=1,{["foo"]=17}}'
而writelua.sh
看起来像这样:
echo "return $1" > bar.lua
然而,最终的结果是bar.lua
的内容:
return version=1
我以为单引号阻止了所有的解释。如何编辑脚本并转义以通过未损坏的原始Lua代码?
单引号阻止了本地主机上的解释。远程主机看到命令行
writelua.sh {version=1,{["foo"]=17}}
这是受支撑扩张。您需要第二组引号,以便将第一组单引号传递到远程主机。
ssh bob writelua.sh "'{version=1,{[\"foo\"]=17}}'"
如你所见,报价开始变得笨拙。更好的解决方案是简单地复制包含的脚本
writelua.sh '{version=1,{["foo"]=17}}'
到远程主机并远程执行。
使用$'...'
引用的示例:
ssh bob writelua.sh $'{version=1,{[\'foo\']=17}}'
使用heredoc
并避免所有过多的引用:
ssh -T bob << \EOF
writelua.sh '{version=1,{["foo"]=17}}'
EOF
这会将原始脚本发送到远程主机,它将在远程主机上进行解释。
当它变得太复杂,特别是有很多转义时,我更喜欢在临时脚本上生成命令,并根据需要在本地或远程通过SSH执行。
但还有另一种选择:使用echo
将命令存储在变量中并利用三个方面:
"$myvar"
之类的内容,而无需转义$
或"
animals='all'; echo love $animals
的东西,让$animals
替换为它的值,而不必转义'
举个例子,如果我想在远程机器上执行这样的事情:
source /my-env.sh; perl -MMYLIB::DB -e 'my $t=db_list("name", 1553786458); print "@$t"'
但是我想从局部变量传递值而不是1553786458
:
now=`date +%s`
我们可以这样:
get_list=`echo 'source /my-env.sh; perl -MMYLIB::DB -e' "'my " '$t=db_list("name", ' "$now" '); print "@$t"' "'"`
您可以看到单引号和双引号是交替的,因此我们不必进行任何转义!它们不需要用空格分隔,但它提高了可读性,在这种情况下不会影响结果。
现在我们可以执行:
ssh user@host $get_list
仍然无法保证这种方法始终有效,所以一旦你建立了命令,最安全的选择就是将它复制到一个文件中。
如果你可以使用Perl ......
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new("bob");
$ssh->system('writelua.sh', '{version=1,{["foo"]=17}}')
or die $ssh->error;
Net::OpenSSH为您照顾quoting的一切。