为什么在 ssh 上运行"pkill -f <anything>"只有在对其结果进行分支时才失败?



发现了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 0也是如此。ssh的文档指出,代码255只是意味着"发生了错误"(超级有用)。

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

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

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

$ 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命令都会自杀)。 但是,如果从子外壳运行,则该逻辑将失败:

$ 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重新编写了一些代码,这样我就可以避免使用"复杂"的远程命令。 从理论上讲,我认为你也可以做一些像pgrep -f <cmd> | grep -v $$ | xargs kill.

最新更新