如何在Linux下以挂起状态启动进程?


19

实际上,我需要一个行为正常的过程,就像我Ctrl+Z刚开始按下它一样。

希望有可能使用Shell脚本来执行此操作。

(另外,知道生成的PID很好,因此我以后可以继续执行该过程。)

Answers:


7

启动进程后,可以将其发送给SIGSTOP以将其挂起。要恢复它,请发送SIGCONT。我认为这个小脚本可能对您有帮助

#!/bin/bash
$@ &
PID=$!
kill -STOP $PID
echo $PID
wait $PID

它运行进程(命令send作为参数),将其挂起,打印进程id并等待其结束。


1
我将其修改为在结尾继续:[enter] #!/bin/bash [enter] $@ & [enter] PID=$! [enter] kill -STOP $PID [enter] echo "Suspended: $PID, press ENTER to continue it" [enter] read [enter] kill -CONT $PID [enter] wait $PID [enter]echo
java.is.for.desktop 2011年

7
众所周知,子流程可能在您没有机会向其发送STOP信号之前就已完成。
MikeyB 2011年

16
在比赛的另一天。
ctrl-alt-delor

23

您是从哪个环境创建流程的?

如果是从C代码等环境中进行操作,则可以fork(),然后在子级中,在exec()之前向自己发送SIGSTOP,以防止进一步执行。

一个更通用的解决方案(可能是最好的)将是创建一个这样做的存根。因此,存根程序将:

  • 接受由真实程序名称和参数组成的参数
  • 向自身发送SIGSTOP
  • exec()具有适当参数的真实程序

这将确保您避免与新处理有关的任何竞争情况都无法在您向其发送信号之前走得太远。


一个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假设您只有一份工作)。

要做一项以上的工作?留给读者练习:)


我希望从shell脚本中执行此操作...
java.is.for.desktop 2011年

太好了,因此,既然您想从shell脚本中执行此操作,请使用存根程序。
MikeyB

20

MikeyB的答案是正确的。从这个问题上的超级用户,这里有一个更简洁的版本:

( kill -SIGSTOP $BASHPID; exec my_command ) &

要理解这一点,需要了解如何在UNIX上启动进程:exec系统调用将使用新程序替换当前正在运行的程序,并保留现有的PID。因此,创建独立进程的方法是:首先fork,然后exec用所需程序替换子进程中正在运行的程序。

此shell命令的成分是:

  1. 括号(...)开始一个子外壳:BASH的另一个实例。
  2. kill命令将STOP信号发送到该进程,从而使其进入挂起状态。
  3. 只要您允许该过程继续进行(通过发送CONT信号),该exec命令就会使它用所需的程序替换my_command保留子外壳的原始PID。
  4. 您可以使用$!变量获取进程的PID。

2
我喜欢这一点,因为它从根本上是正确的(只是我不得不使用-s STOP代替-SIGSTOP)。仍然奇怪:为什么必须$BASHPID代替它$$?(我可能不太了解其中的区别)。
Hibou57 2014年

1
对于$$vs $BASHPID,我检查后者是子外壳的PID,而不是前者。有一个有趣的问题:在bash脚本中应用提示,大多数情况下会失败,并且我必须执行以下操作:PID=$!; ps -p $PID; kill -s CONT $PID;…如果我删除了该ps -p $PID部件,它将失败:该过程似乎消失了(杀死了?),而没有任何错误消息。从交互式外壳程序可以,问题仅在于脚本。太神秘了。
Hibou57 2014年

我试图使用此解决方案列出my_command的文件描述符。(goo.gl/cNbUE8),但描述符仍然相同,无论如何,my_command是什么。
rasty.g

有关替换$BASHPIDbash以外的外壳的选项,请参见此处
Jakob,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.