为什么 运行 "pkill -f <anything>" over ssh 仅在其结果分支时失败?

Why does running "pkill -f <anything>" over ssh fail only when branching on its result?

发现 pkillssh 之间有趣的互动。在这里记录下来以供后代使用:

$ ssh user@remote 'false'; echo $?                                                              
1

$ ssh user@remote 'false || echo "failed"'; echo $?
failed
0

$ ssh user@remote 'pkill -f "fake_process"'; echo $?                                               
1

$ ssh user@remote 'pkill -f "fake_process" || echo "failed"'; echo $?
255

似乎示例#4 应该与#2 具有相同的输出; falsepkill -f "fake_process" 都以代码 1 退出并且没有输出。然而,#4 将始终以代码 255 退出,即使远程命令显式调用 exit 0ssh 的文档指出代码 255 只是意味着 "an error occurred"(超级有用)。

(exit 1)ls fake_filekill <non-existent PID> 等替换 pkill 命令,一切都按预期工作。此外,当 运行 在本地(而不是通过 ssh)时,这些匹配符合预期。

问题似乎是 pkill 正在自杀。或者更确切地说,它正在杀死拥有它的 shell。

首先,ssh 似乎使用远程用户的 shell 来执行某些 "complicated" 命令:

$ ssh user@remote 'ps -F --pid $$'
UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
user      9531  9526  0 11862  1616   6 14:36 ?        00:00:00 ps -F --pid 9531

$ ssh user@remote 'ps -F --pid $$ && echo hi'
UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
user      9581  9577  0 28316  1588   5 14:36 ?        00:00:00 bash -c ps -F --pid $$ && echo hi
hi

其次,似乎 pkill -f 通常知道不要自杀(否则所有 pkill -f 命令都会自杀)。但是,如果 运行 来自子 shell,则该逻辑失败:

$ pkill -f fake_process; echo $?
1

$ sh -c 'pkill -f fake_process'; echo $?
[1]    14031 terminated  sh -c 'pkill -f fake_process'
143

就我而言,为了解决这个问题,我只是重新编写了 ssh/pkill 周围的一些代码,这样我就可以避免使用 "complicated" 远程命令。理论上我认为你也可以做类似 pgrep -f <cmd> | grep -v $$ | xargs kill.

的事情