如何通过具有默认csh shell的ssh远程执行交互式多行bash脚本?

时间:2018-10-12 07:10:49

标签: bash ssh csh

我正在编写一个脚本,该脚本使我能够通过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解析问题是否可以解决?

2 个答案:

答案 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,该解析器标识需要转义的结构。