关于处理任意争论

关于处理任意争论

我编写了一个在本地执行时运行良好的脚本:

./sysMole -time Aug 18 18

论据“-时间”,“八月”,“18”, 和“18”已成功传递到脚本。

现在,该脚本被设计为在远程计算机上执行,但是从本地计算机上的本地目录执行。例子:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole

这也很好用。但当我尝试包含上述论点时,问题就出现了(-时间2018年8月18日), 例如:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole -time Aug 18 18

运行该脚本后,我收到以下错误:

bash: cannot set terminal process group (-1): Invalid argument
bash: no job control in this shell

请告诉我我做错了什么,这非常令人沮丧。

答案1

你的例子非常接近。当您将它与诸如此类的参数一起使用时,它工作得很好。

示例脚本:

$ more ex.bash 
#!/bin/bash

echo $1 $2

有效的示例:

$ ssh serverA "bash -s" < ./ex.bash "hi" "bye"
hi bye

但对于这些类型的参数它会失败:

$ ssh serverA "bash -s" < ./ex.bash "--time" "bye"
bash: --: invalid option
...

这是怎么回事?

您遇到的问题是参数-time--time在我的示例中被解释为切换到bash -s。您可以bash通过使用参数终止它为自己获取任何剩余的命令行参数来进行安抚--

像这样:

$ ssh root@remoteServer "bash -s" -- < /var/www/html/ops1/sysMole -time Aug 18 18

例子

#1:

$ ssh serverA "bash -s" -- < ./ex.bash "-time" "bye"
-time bye

#2:

$ ssh serverA "bash -s" -- < ./ex.bash "--time" "bye"
--time bye

#3:

$ ssh serverA "bash -s" -- < ./ex.bash --time "bye"
--time bye

#4:

$ ssh  < ./ex.bash serverA "bash -s -- --time bye"
--time bye

笔记:只是为了明确一点,重定向出现在命令行上的任何位置都没有区别,因为ssh无论如何都会使用其参数的串联来调用远程 shell,引用并没有太大区别,除非您需要在远程 shell 上引用,例如例子#4:

$ ssh  < ./ex.bash serverA "bash -s -- '<--time bye>' '<end>'"
<--time bye> <end>

答案2

关于处理任意争论

如果您真的只使用单个字符串,即。-time Aug 18 18,那么您可以简单地对它进行硬编码,现有的答案会告诉您如何充分做到这一点。另一方面,如果您需要传递未知参数(例如要在其他系统上显示的消息,或者最终用户可以控制其名称的位置所创建的文件的名称),则需要更加小心。


bashksh作为/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"
}

与任何 POSIX 兼容的/bin/sh

printf %q为了安全地防范足够恶意的参数数据(当转义的字符串中存在不可打印字符时,尝试利用 bash 中使用的不符合 POSIX 的引用),即使/bin/sh使用基线 POSIX(例如dashash),它变得更有趣一点:

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
}

用法(适用于上述任一情况)

然后可以调用上面给出的函数:

# if your time should be three arguments
runRemote /var/www/html/ops1/sysMole -time Aug 18 18

...或者...

# if your time should be one string
runRemote /var/www/html/ops1/sysMole -time "Aug 18 18"

答案3

将命令用引号引起来,如下所示:

ssh myserver "date +\"Date: %Y%m%d %H:%M\";printf \"Uptime: \";uptime;printf \"uname: \";uname -a"
Date: 20200409 20:02
Uptime:  20:02:29 up 66 days, 55 min,  2 users,  load average: 0.06, 0.05, 0.08
uname: Linux zltcmtn23aecc1rx7322 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Connection to 105.31.182.217 closed.

答案4

假设 aa 是包含 ls 的本地文件

$ssh servername "cat | bash" < a.a

将 127.0.0.1 更改为您的远程 IP 地址

这两个给出了有关伪 tty 分配的消息,但它们可以工作。

$ cat a.a | ssh 127.0.0.1

$ ssh 127.0.0.1 <a.a

或者

$ cat a.a | ssh 127.0.0.1 bash or

$ ssh 127.0.0.1 bash < a.a

相关内容