如何终止进程(由 运行-process 创建)

How to kill process (created by run-process)

我想终止由 (sb-ext:run-program) 启动的进程。

(let ((process (sb-ext:run-program "/path/to/process.sh" '() :wait nil)))
  (sleep 10)
  (sb-ext:process-close process)
  (sb-ext:process-kill process 9 :pid))

根据SBCL-Manual (sb-ext:process-kill process 9 :pid) should send SIGKILL (which has value 9)process,因此消灭这个过程。

但是当我尝试通过虚拟进程使用它时:

#!/bin/bash

i=0
while [ $i -lt 4 ]
do
sleep 5
i+=1
done

它留下了一个甚至无法使用 htop + kill 杀死的军团。

执行前的进程树如下所示:

|- /usr/bin/emacs
| |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl

执行期间:

|- /usr/bin/emacs
| |- /usr/local/bin/sbcl
| | |- /bin/bash /path/to/process.sh
| | | |- sleep 5
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl

执行后(除非main sbcl是killed/stopped,否则process.sh不会终止):

|- /usr/bin/emacs
| |- /usr/local/bin/sbcl
| | |- process.sh
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl

当手动启动并使用 Ctr-Chtop + kill.

时,可以很好地终止脚本

因此如何在 sbcl 中实现 seamless/corpsless 杀戮?

使用时也会发生同样的情况:

(let ((process (sb-ext:run-program "/usr/local/bin/sbcl" '("--dynamic-space-size" "512" "--eval" "(sleep 100)") :wait nil)))
  (sleep 10)
  (sb-ext:process-close process)
  (sb-ext:process-kill process 9 :pid))

解决方案如下所示(如果您使用与流程关联的流,则需要流程关闭):

(let ((process (sb-ext:run-program "/home/user/processTest.sh" '() :wait nil)))
  (sleep 10)
  (sb-ext:process-kill process 15 :pid)
  (sb-ext:process-wait process)
  (sb-ext:process-close process)
  (sb-ext:process-exit-code process))   

或者正如 Sylvester 指出的那样,您可以省略 process-close(如果您没有任何与流程关联的流):

(let ((process (sb-ext:run-program "/home/user/processTest.sh" '() :wait nil)))
  (sleep 10)
  (sb-ext:process-kill process 15 :pid))                                

process-close 影响过程的方式将成为 zombie.

This occurs for child processes, where the entry is still needed to allow the parent process to read its child's exit status.

一旦通过 process-exit-code 读取退出状态,进程就会被回收并将消失。

如果你使用的是便携式 uiop:run-program 而不是 sbcl 的,你可以通过第二次调用 运行-program 来终止 PID,给它 kill 命令,就像你一样会在 shell:

(uiop:run-program (format nil "kill ~a" (process-info-pid process)))

其中 process 是初始 run-program 的 return 结果,即启动您要终止的进程的结果。