实际上,我需要一个行为像我刚刚按下Ctrl+Z
它一样的进程。
希望可以使用 shell 脚本来做这样的事情。
(此外,了解最终的 PID 也很好,这样我就可以继续该过程。)
答案1
启动进程后,您可以发送 SIGSTOP 来暂停它。要恢复它,请发送 SIGCONT。我认为这个小脚本可能会对你有所帮助
#!/bin/bash
$@ &
PID=$!
kill -STOP $PID
echo $PID
wait $PID
它运行进程(命令作为参数发送),暂停它,打印进程 ID 并等待它结束。
答案2
您从哪个环境创建该流程?
如果您在 C 代码等环境中执行此操作,则可以 fork(),然后在子进程中,在 exec() 之前向您自己发送 SIGSTOP,以防止进一步执行。
一个更通用的解决方案(可能是最好的)是创建一个存根来实现这一点。因此,存根程序将:
- 接受由实际程序的名称和参数组成的参数
- 向自己发送 SIGSTOP
- 使用适当的参数执行真正的程序
这将确保您避免在向新处理发送信号之前发生任何与新处理有关的竞争条件。
以 shell 为例:
#!/bin/bash
kill -STOP $$
exec "$@"
使用以上代码:
michael@challenger:~$ ./stopcall.sh ls -al stopcall.sh
[1]+ Stopped ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ jobs -l
[1]+ 23143 Stopped (signal) ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ kill -CONT 23143; sleep 1
-rwxr-xr-x 1 michael users 36 2011-07-24 22:48 stopcall.sh
[1]+ Done ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$
显示jobs -l
PID。但是如果您从 shell 执行此操作,则不需要直接获取 PID。您可以直接执行:(kill -CONT %1
假设您只有一项工作)。
用多个作业来做?留给读者练习吧 :)
答案3
MikeyB 的回答是正确的。来自这个问题对于超级用户来说,这里有一个更简洁的版本:
( kill -SIGSTOP $BASHPID; exec my_command ) &
要理解这一点,我们需要了解 Unix 上进程的启动方式:exec
系统调用用新程序替换当前正在运行的程序,保留现有的PID。因此,创建独立进程的方式是,首先fork
,然后exec
用所需的程序替换子进程中正在运行的程序。
这个shell命令的组成部分是:
- 括号
(...)
启动一个子 shell:BASH 的另一个实例。 - 该
kill
命令向该进程发送 STOP 信号,使其进入暂停状态。 - 只要你允许进程继续(通过发送信号
CONT
),exec
命令就会让它取代自身使用您想要的程序。my_command
保留子 shell 的原始 PID。 - 您可以使用该
$!
变量来获取进程的 PID。