我正在编写一个脚本,该脚本使我能够通过SSH远程执行其他本地bash脚本,而无需上传它们。我的一些服务器装有Linux,一些FreeBSD的默认设置为csh。到目前为止,我已经介绍了以下内容:
ssh remote_server 'bash -c '\'"$(cat local_script.sh)"\'' script_parameters'
这使我可以在remote_server上执行local_script.sh,支持交互性(例如,“ read”命令将在local_script.sh中起作用),并且可以将位置参数传输到脚本。问题是,如果local_script.sh有多行,则以上代码仅适用于具有bash默认外壳的远程服务器。在FreeBSD上,sshd首先启动csh以执行“ bash -c”命令,并尝试将脚本代码($(cat local_script.sh)的结果)传递给它作为第一个参数。但是由于此代码是多行代码,并且csh希望将结束语引号与开始语引号放在同一行,因此我得到了“ Unmatched'”。错误。因此,csh不能解析此转义的多行参数以将其传递给bash进程。
我现在看到的唯一解决方案是解析local_script.sh并使用“;”将其自动重写为单行代码。分隔符,然后再通过SSH传递。但这需要创建另一个脚本,而且似乎并不容易。因此,我想问一下这个csh miltiline解析问题是否可以解决?
答案 0 :(得分:1)
使用标准输入/dev/stdin
怎么样?
ssh remote_server bash /dev/stdin script_parameters < local_script.sh
使用两个不同的命令和临时文件
重击
ssh remote_server $'tmp=`mktemp tmp.XXXXXX`;cat <<\'HEREDOC_END\' >"$tmp"
'"$(cat local_script.sh)"'
HEREDOC_END
bash "$tmp" script_parameters ;rm "$tmp"'
csh
ssh remote_server 'set tmp=`mktemp tmp.XXXXXX`;cat <<"HEREDOC_END" >"$tmp"
'"$(cat local_script.sh)"'
"HEREDOC_END"
bash "$tmp" script_parameters ;rm "$tmp"'
答案 1 :(得分:0)
在这种情况下,无需保留最外面的引号。
ssh remote_server bash -c "\"$(cat local_script.sh)\"" script_parameters
这并不完全可靠;例如,local_script.sh
中的单引号不会逐字引用文本。所以下面的例子
echo 'fnord "$(echo yes)"'
即使字符串用单引号括起来,也会对命令替换进行远程评估。在一般情况下,基本上必须用一个外壳解析器替换cat
,该解析器标识需要转义的结构。