ssh 远程命令:被信号 15 终止

ssh 远程命令:被信号 15 终止

脚本:

#!/usr/bin/env bash
set -e
set -u
set -x
set -o pipefail

hosts=(
    host1
    host2
)
for host in ${hosts[@]}
do
  ssh $host 'pids=$(ps -aux|pgrep -f "/usr/bin/nmon"); kill $pids; wait $pids 2>/dev/null'
done

输出:

+ for host in '${hosts[@]}'
+ ssh host1 'pids=$(ps -aux|pgrep -f "/usr/bin/nmon" |awk "{print $2}") ; kill $pids ; wait $pids 2>/dev/null'
Killed by signal 15.

我已经使用过wait捕获信号,但还是不起作用?
任何帮助都将不胜感激!

答案1

我认为这里发生的事情是pgrep -f "/usr/bin/nmon"也匹配运行该命令的 shell,因为它会在完整命令行中找到字符串“/usr/bin/nmon”,并且您指定 -f 在整个命令行中查找字符串(而不仅仅是进程名称......)

您的脚本中有很多不正确的地方:

ps -aux|pgrep -f "/usr/bin/nmon"

或者:

ps -aux|pgrep -f "/usr/bin/nmon" |awk "{print $2}"

这完全是错误的。pgrep 可以独立工作,不需要任何管道。ps ... | grep ...是一个东西,但是 pgrep 会在进程列表本身中查找模式,因此不需要ps。您也不需要awk剪切字段,因为 pgrep 已经只返回了 PID。

然后:

kill $pids

不要使用 pgrep 查找 pid,然后用单独的命令杀死它们……相反,直接使用 pkill 就好!pkill 是 pgrep 的兄弟,它将查找进程并向它们发送终止信号。您甚至可以看到 pgrep 和 pkill 共享相同的手册页因为它们非常相似。

wait $pids

这也行不通……因为你只能调用wait当前进程的子进程。你不能在任何进程上调用它。考虑到你刚刚通过 ssh 打开了这个 shell,你真的不能等待这些已经存在的进程……

因此,简而言之:没有管道,直接使用 pkill,省略 -f(因此它只匹配 /usr/bin/nmon 命令)并且不要等待:

for host in "${hosts[@]}" ; do
    ssh "$host" pkill /usr/bin/nmon
done

简单的!

我还为您修复了 shell 引用... 简而言之:您需要对所有扩展为单个单词的变量使用双引号。好吧,数组也一样。

我希望这有帮助!

相关内容