据我了解,工作是管道从某个 shell 启动,您可以在该 shell 内管理这些作业( fg
、 、 Ctrl-Z )。bg
一个作业可以由多个进程/命令组成。
我的问题是,当原始的包含 shell 退出时,这些作业会发生什么?假设未设置 huponexit,因此后台进程在 shell 退出后继续运行。
假设我已经做了:
$ run.sh | grep 'abc' &
[1] job_id
然后我退出这个 shell。我将进入一个新的 shell 并运行jobs
,但看不到任何明显的东西。但我可以ps aux | grep run.sh
看到这个进程正在运行,我也会ps aux | grep grep
看到这个进程正在grep 'abc'
运行。
有没有一种方法可以获取整个管道的作业 ID,以便我可以一次性杀死它,或者一旦退出原始 shell,我是否必须从另一个 shell 中单独杀死所有进程? (我已经尝试过后者并且它有效,但跟踪所有过程似乎很麻烦。)
答案1
当 shell 退出时,它可能会向后台作业发送 HUP 信号,这可能会导致它们退出。仅当 shell 本身收到 SIGHUP 时才会发送 SIGHUP 信号,即仅当终端消失时(例如,因为终端仿真器进程终止),而不是在正常退出 shell 时(使用内置命令exit
或键入Ctrl+ D)。看在哪些情况下,注销时不会向作业发送 SIGHUP?和是否存在子进程与其父进程一起死亡的 UNIX 变体?更多细节。在 bash 中,您可以设置huponexit
选项以在正常退出时也向后台作业发送 SIGHUP。在 ksh、bash 和 zsh 中,调用disown
作业会将其从要向其发送 SIGHUP 的作业列表中删除。接收到 SIGHUP 的进程可能会忽略或捕获该信号,然后它就不会死亡。nohup
在运行程序时使用它可以使其不受 SIGHUP 的影响。
如果该进程没有由于可能的 SIGHUP 而被终止,那么它会保留在后面。没有任何东西可以将其与 shell 中的作业编号关联起来。
如果进程尝试访问终端但终端已不存在,则该进程仍可能死亡。这取决于程序如何对不存在的终端做出反应。
如果作业包含多个进程(例如管道),则所有这些进程都在一个进程中进程组。进程组的发明正是为了捕捉由多个相关进程组成的 shell 作业的概念。您可以通过显示进程组 ID(PGID — 通常是组中第一个进程的进程 ID)来查看按进程组分组的进程,例如在ps l
Linux 或类似ps -o pid,pgid,tty,etime,comm
portably 下。
您可以通过向 传递一个负参数来终止组中的所有进程kill
。例如,如果您确定要终止的管道的 PGID 是 1234,那么您可以使用以下命令终止它:
kill -TERM -1234
答案2
一般来说,它们仍然会运行,但您应该使用 nohup,如果您忘记或改变主意,请使用 disown。
mike@mike-laptop4:~$ sleep 500
^Z
[1]+ Stopped sleep 500
mike@mike-laptop4:~$ bg
[1]+ sleep 500 &
mike@mike-laptop4:~$ jobs
[1]+ Running sleep 500 &
mike@mike-laptop4:~$ disown %1
mike@mike-laptop4:~$ jobs
mike@mike-laptop4:~$