Answers:
为什么
sleep
注销并关闭终端后该过程仍然存在?在我看来,nohup
注销过程中除守护程序和程序外的所有内容都会被杀死。如果sleep
可以通过这种方式生存下来,是否意味着我可以使用此方法代替nohup
命令?
除非由bash
产生的实例设置ssh
了huponexit
选项,否则退出/注销后不会以任何方式终止任何进程,并且当huponexit
设置了该选项时,kill -9
在shell上使用替代nohup
在shell的子进程上使用不是很好的选择。nohup
外壳程序的子进程上的进程仍将保护它们免受不来自该外壳程序的SIGHUP的影响,即使那并不重要nohup
,仍然是首选,因为它允许外壳程序正常终止。
其中bash
有一个名为的选项huponexit
,如果设置了该选项,它将bash
在退出/注销时使SIGHUP成为其子级;
在交互式非登录 bash
实例中,例如在由bash
产生的实例中gnome-terminal
,此选项将被忽略;无论huponexit
设置还是取消设置,bash
的孩子bash
在退出时都不会被SIGHUPped挡住;
在交互式登录 bash
实例中,例如在由bash
产生的实例中ssh
,不会忽略此选项(但是默认情况下未设置)。如果huponexit
设置为,bash
则bash
退出/注销时,的孩子将被SIGHUPped屏蔽;如果huponexit
未设置,bash
则bash
退出/注销后,的孩子将不会被SIGHUPped ;
因此,通常,从交互式登录bash
实例退出/注销,除非huponexit
设置了该选项,否则不会使shell SIGHUP成为其子代,而从交互式非登录bash
实例退出/退出将不会使shell SIGHUP成为其子代而不管;
但是,在这种情况下这是无关紧要的:kill -9
sleep
无论使用哪种方式都可以生存,因为杀死其父进程(bash
)不会给后者留下任何对前者执行任何操作的机会(例如,如果当前bash
实例是登录bash
实例,并将huponexit
选项设置为SIGHUP)。
此外,与其他信号(例如发送给的SIGHUP信号bash
)不同,SIGKILL信号从不传播到进程的子进程,因此sleep
甚至不会被杀死。
nohup
启动一个不受SIGHUP信号影响的过程,这是有所不同的;它将防止进程在接收到SIGHUP信号时挂起,在这种情况bash
下,如果huponexit
设置了选项并且退出了shell ,则交互式登录实例可以接收到该信号;因此,从技术上讲,使用未设置选项nohup
的交互式登录bash
实例来启动进程huponexit
将防止进程在收到SIGHUP信号后挂机,但是退出/注销shell不管如何都不会SIGHUP。
但是,总的来说,当nohup
需要防止SIGHUP信号从父shell发出时,没有理由偏爱kill -9
on父方法而不是nohup
on子方法。相反,应该相反。
使用该kill -9
方法杀死父对象不会使父对象优雅退出,而使用该nohup
方法启动子对象会使父对象被其他信号终止,例如SIGHUP(在上下文中做一个有意义的例子)的孩子开始使用nohup
),可以让它正常退出。
ps -e | grep process
则应将过程与PID一起列出(或者,pgrep -x process
如果您确定匹配单个进程而不是未拥有的事物,则更好);问题是,当您杀死一个进程时,kill -9
该进程的子进程由拥有upstart
,因此其原始PPID丢失,并且其PPID更改为新贵的PID,从而使其无法识别(AFAIK),但对于其名称或PID
nohup
将无法防止从父进程收到SIGHUP信号后进程挂起?我正在尝试通过在后台(在PuTTY SSH shell终端中)运行一个进程nohup <command> <arg> &
。当我通过单击PuTTY X
按钮注销时,后台进程将立即终止。当我通过输入exit
PuTTY SSH Shell终端注销时,该过程将继续在后台运行。
bash
默认情况下,退出时不向子进程发送HUP信号。更详细(感谢@kos),它从未在非登录shell中使用。
如果设置该选项,则可以将bash配置为针对登录shell执行此操作huponexit
。在终端中,执行以下操作:
[romano:~] % bash -l
(这将启动一个新的“登录” shell)
romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout
现在检查该sleep
过程:
[romano:~] % ps augx | grep sleep
romano 32231 0.0 0.0 16000 2408 pts/11 S+ 15:23 0:00 grep sleep
...未运行:它已收到HUP信号并按要求退出。
sleep 1000 & ; exit
能sleep
幸存下来,那为什么呢?请注意,如果我执行kill -HUP
该sleep
过程,它将退出。并且即使生存huponexit
,sleep
生存。困惑...(我将尝试更好地理解并修改该asnwer,否则我将其删除)。
如果
sleep
可以这种方式生存,是否意味着我可以使用此方法代替nohup
命令?
kill -9
确实不是应该走的路。这就像在电视上用枪射击时将其关闭。除了喜剧组件之外,没有任何优势。进程无法捕获或忽略SIGKILL
。如果您没有给该进程完成操作和清理的机会,则可能会留下损坏的文件(或其他状态),并且无法再次启动。kill -9
当别无他法时,这是最后的希望。
为什么注销并关闭终端后睡眠过程仍然可以生存?在我看来,注销时除守护程序和nohup程序以外的所有内容都将被杀死。
您遇到的情况是:
的父进程sleep
是当前正在运行的bash
shell。当您执行kill -9
bash时,bash进程没有机会将a发送SIGHUP
给其任何子进程,因为SIGKILL
(由发送kill -9
)由该进程捕获。睡眠过程继续运行。睡眠现在变成了一个孤儿的过程。
初始化(PID 1)进程执行一种称为重命名的机制。这意味着init进程现在成为该孤立进程的父级。init是一个例外,进程可以成为它的子进程,因为它收集丢失了其原始父进程的进程。顺便说一句:sshd
“进入后台” 守护程序(如)执行该操作。
如果那不会发生,那么孤立的进程将在以后(完成时)成为僵尸进程。这是什么时候waitpid()
不被调用(父进程的责任,当该进程被杀死时无法履行)所发生的事情。init会waitpid()
在特定的时间间隔内进行调用以避免僵尸孩子。
TERM
或HUP
huponext
。TERM将等到睡眠结束。如果是OP的睡眠命令,那将是数千年=)
使用&
将导致程序在后台运行。要在后台使用bg
命令查看程序,并再次使其作为前台运行,请运行fg
。
是的,有很多方法可以使程序即使在主终端退出时也能运行。
huponexit
仅适用于登录外壳,例如通过的外壳ssh
(而不是通过的外壳gnome-terminal
)
&
会将进程派生到后台(例如守护程序),即使您已注销也可以继续运行。