我写了一个bash脚本foo.sh
#!/usr/bin/env bash echo "starting the script";
我想在我的远程服务器上执行它。 我试过ssh user@remote-addr < test.sh
和它的工作。
之后,我改变了这样的test.sh文件
#!/usr/bin/env bash echo "starting the script"; echo $1;
现在我想传递一个本地参数来执行我的脚本,但是当我键入ssh user@remote-addr < test.sh testparam
它会返回一个错误。
我怎样才能传递参数与我的脚本?
使用-s
选项,它强制bash
(或任何与POSIX兼容的shell)从标准输入读取其命令,而不是从第一个位置参数指定的文件中读取。 所有参数都被视为脚本的参数。
ssh user@remote-addr 'bash -s arg' < test.sh
bash
或者ksh
作为/bin/sh
如果远程/bin/sh
是由bash或ksh提供的,那么可以安全地使用不可信的参数列表执行以下操作,这样甚至可以将安全的名称(如$(rm -rf $HOME).txt
)作为参数安全地传递:
runRemote() { local args script script=$1; shift # generate eval-safe quoted version of current argument list printf -v args '%q ' "$@" # pass that through on the command line to bash -s # note that $args is parsed remotely by /bin/sh, not by bash! ssh user@remote-addr "bash -s -- $args" < "$script" }
此后…:
runRemote test.sh testparam
/bin/sh
请注意,以下内容仍然需要在bash
运行,但只要远程计算机安装了bash
,系统正在进入ssh
进程就有一个/bin/sh
是POSIX-baseline 。
为了防止充分恶意的参数数据(即使使用基线为POSIX的/bin/sh
,试图利用bash中printf %q
使用的非POSIX兼容引用(在bash中存在不可打印字符时) (如dash
或ash
),它会变得更有趣:
runRemote() { local script=$1; shift local args printf -v args '%q ' "$@" ssh user@remote-addr "bash -s" <<EOF # pass quoted arguments through for parsing by remote bash set -- $args # substitute literal script text into heredoc $(< "$script") EOF }
同样被调用为:
runRemote test.sh testparam