All*_*enD 145 shell scripting bash options shell-script
我编写了一个在本地执行时运行良好的脚本:
./sysMole -time Aug 18 18
Run Code Online (Sandbox Code Playgroud)
参数"-time"、"Aug"、"18"和"18"成功传递给脚本。
现在,这个脚本被设计为在远程机器上执行,但是从本地机器上的本地目录执行。例子:
ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole
Run Code Online (Sandbox Code Playgroud)
这也很好用。但是当我尝试包含上述参数(-time Aug 18 18) 时,问题就出现了,例如:
ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole -time Aug 18 18
Run Code Online (Sandbox Code Playgroud)
运行该脚本后,我收到以下错误:
bash: cannot set terminal process group (-1): Invalid argument
bash: no job control in this shell
Run Code Online (Sandbox Code Playgroud)
请告诉我我做错了什么,这非常令人沮丧。
slm*_*slm 202
你很接近你的例子。当您将它与诸如此类的参数一起使用时,它工作得很好。
示例脚本:
$ more ex.bash
#!/bin/bash
echo $1 $2
Run Code Online (Sandbox Code Playgroud)
有效的例子:
$ ssh serverA "bash -s" < ./ex.bash "hi" "bye"
hi bye
Run Code Online (Sandbox Code Playgroud)
但是对于这些类型的参数它失败了:
$ ssh serverA "bash -s" < ./ex.bash "--time" "bye"
bash: --: invalid option
...
Run Code Online (Sandbox Code Playgroud)
您遇到的问题是参数 ,-time或--time在我的示例中,被解释为切换到bash -s。您可以bash通过使用--参数终止它为自己获取任何剩余的命令行参数来安抚它。
像这样:
$ ssh root@remoteServer "bash -s" -- < /var/www/html/ops1/sysMole -time Aug 18 18
Run Code Online (Sandbox Code Playgroud)
#1:
$ ssh serverA "bash -s" -- < ./ex.bash "-time" "bye"
-time bye
Run Code Online (Sandbox Code Playgroud)
#2:
$ ssh serverA "bash -s" -- < ./ex.bash "--time" "bye"
--time bye
Run Code Online (Sandbox Code Playgroud)
#3:
$ ssh serverA "bash -s" -- < ./ex.bash --time "bye"
--time bye
Run Code Online (Sandbox Code Playgroud)
#4:
$ ssh < ./ex.bash serverA "bash -s -- --time bye"
--time bye
Run Code Online (Sandbox Code Playgroud)
注意:只是为了说明重定向出现在命令行上的任何地方都没有区别,因为ssh无论如何调用远程shell并连接其参数,引用没有太大区别,除非您需要在远程shell上引用就像例子#4:
$ ssh < ./ex.bash serverA "bash -s -- '<--time bye>' '<end>'"
<--time bye> <end>
Run Code Online (Sandbox Code Playgroud)
如果你真的只使用一个字符串,即。-time Aug 18 18,然后您可以简单地对其进行硬编码,现有的答案会告诉您如何充分地做到这一点。另一方面,如果您需要传递未知参数(例如要在其他系统上显示的消息,或者在最终用户可以控制其名称的位置创建的文件的名称),则需要更加小心。
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"
}
Run Code Online (Sandbox Code Playgroud)
/bin/sh为了安全地抵御足够恶意的参数数据(printf %q当被转义的字符串中存在不可打印的字符时,尝试利用bash 中使用的非 POSIX 兼容引用),即使/bin/sh是基线 POSIX(例如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
}
Run Code Online (Sandbox Code Playgroud)
然后可以调用上面给出的函数:
# if your time should be three arguments
runRemote /var/www/html/ops1/sysMole -time Aug 18 18
Run Code Online (Sandbox Code Playgroud)
...或者...
# if your time should be one string
runRemote /var/www/html/ops1/sysMole -time "Aug 18 18"
Run Code Online (Sandbox Code Playgroud)