bash 为什么有时退出 shell 时 Unix 后台进程会死掉?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1463852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do unix background processes sometimes die when I exit my shell?
提问by Steven Schlansker
I wanted to know why i am seeing a different behaviour in the background process in Bash shell
我想知道为什么我在 Bash shell 的后台进程中看到不同的行为
Case 1: Logged in to Unix server using Putty(SSH)
案例一:使用Putty(SSH)登录Unix服务器
- By default it uses csh shell
- I changed to bash shell
- typed sleep 2000 &
- press enter
- 默认情况下它使用 csh shell
- 我改成 bash shell
- 键入 sleep 2000 &
- 按回车
It gave me the job number. Now i killed my session by clicking the x in the putty window Now open another session and tried to lookup the process..the process died.
它给了我工作号。现在我通过单击腻子窗口中的 x 终止了我的会话 现在打开另一个会话并尝试查找进程..进程终止了。
Case 2:Case 1: Logged in to Unix server using Putty(SSH) By default it uses csh shell
案例2:案例1:使用Putty(SSH)登录Unix服务器默认使用csh shell
- I changed to bash shell
- vi mysleep.sh
- sleep 2000 & Saved mysleep.sh
- ./mysleep.sh
- 我改成 bash shell
- vi mysleep.sh
- sleep 2000 并保存 mysleep.sh
- ./mysleep.sh
Diff here is..instead of executing the sleep command directly i am storing the sleep command in a file and executing the file.
这里的区别是..我没有直接执行 sleep 命令,而是将 sleep 命令存储在一个文件中并执行该文件。
Now i killed my session by clicking the x in the putty window Now open another session and tried to lookup the process..the process is still there
现在我通过单击腻子窗口中的 x 终止了我的会话 现在打开另一个会话并尝试查找进程..进程仍然存在
Not sure why this is happening. I thought i need to do disown in bash to run the process even after logging out.
不知道为什么会这样。我想我需要在 bash 中做 disown 才能运行这个过程,即使在注销后也是如此。
One diff i see in the parent process id..In the second case..the parent process id for the sleep 2000 becomes 1. Looks like as soon as process for mysleep.sh died the kernel assigned the parent process to 1.
我在父进程 id 中看到的一个差异..在第二种情况下.. sleep 2000 的父进程 id 变为 1。看起来 mysleep.sh 的进程一死,内核就将父进程分配给 1。
回答by Steven Schlansker
The difference here is indeed the intervening process. When you close the terminal window, a HUP signal (related to "nohup" as an0nymo0usc0ward mentioned) is sent to the processes running in it. The default action on receiving HUP is to die - from the signal(3) manpage,
这里的区别确实是中间过程。当您关闭终端窗口时,一个 HUP 信号(与 an0nymo0usc0ward 提到的“nohup”相关)被发送到其中运行的进程。接收 HUP 的默认操作是死亡 - 从信号(3)联机帮助页,
No Name Default Action Description
1 SIGHUP terminate process terminal line hangup
In your first example, the sleep process directly receives this HUP signal and dies because it isn't set to do anything else. (Some processes catch HUP and use it to perform some action, e.g. reread some configuration files)
在您的第一个示例中,睡眠进程直接接收此 HUP 信号并死亡,因为它没有设置为执行任何其他操作。(某些进程捕获 HUP 并使用它来执行某些操作,例如重新读取某些配置文件)
In the second example, the shell process running your shell script has already died, so the sleep process never gets the signal. In UNIX, every process must have a parent process due to the internals of how the wait(2) family of calls works and indeed processes in general. So when the parent process dies, the kernel gives it to init (pid 1, as you note) as a foster child. Orphan process (on wikipedia)has some more information available about it, also see Zombie processfor some additional technical details.
在第二个示例中,运行您的 shell 脚本的 shell 进程已经死亡,因此 sleep 进程永远不会收到信号。在 UNIX 中,由于 wait(2) 调用系列的工作原理以及通常的进程的内部原理,每个进程都必须有一个父进程。因此,当父进程终止时,内核会将其作为寄养子进程交给 init(pid 1,如您所见)。 孤儿进程(在维基百科上)有一些关于它的更多信息,另请参阅僵尸进程以获取一些其他技术细节。
回答by Jayan
Already running process?
已经在运行进程?
^z
bg
disown %<jobid>
^z
bg
不承认 %<jobid>
New process/script (on local machine's console)?
新进程/脚本(在本地机器的控制台上)?
nohup script.sh &
nohup 脚本.sh &
New process/script (on remote machine's console)?
新进程/脚本(在远程机器的控制台上)?
Depending on your need,
there are two options [ there will be more ;-) ]
根据您的需要,
有两种选择 [ 会有更多 ;-) ]
ssh remotehost 'nohup /path/to/script.sh </dev/null> nohup.out 2>&1 &'
ssh</dev/null远程主机'nohup /path/to/script.sh > nohup.out 2>&1 &'
OR
或者
use 'screen'
使用“屏幕”
回答by an0nym0usc0ward
Try "nohup cmd args..."
尝试“nohup cmd args...”
回答by Arnout
Steven's answer is correct, but I'd like to highlight the tricky part here again:
史蒂文的回答是正确的,但我想在这里再次强调棘手的部分:
=> Using a bash script that just executes sleep in the background
=> 使用只在后台执行 sleep 的 bash 脚本
The effect of this is that the "script" exits almost immediately (since it's done all its commands). However, it did create a child process (sleep) during its lifetime. The effect of this is that:
这样做的结果是“脚本”几乎立即退出(因为它完成了所有命令)。但是,它确实在其生命周期内创建了一个子进程(睡眠)。这样做的效果是:
- The "script" cannot be the parent anymore, and sleep is orphaned to init (which shows nicely in a pstree)
- The bash shell where you started the script from has no underlying jobs anymore
- “脚本”不再是父级,并且 sleep 被孤立到 init (在 pstree 中很好地显示)
- 用于启动脚本的 bash shell 不再有底层工作
Note that this stuff all happens when you executed the script, and has nothing to do with any ssh logout/putty closing.
请注意,这些东西都是在您执行脚本时发生的,与任何 ssh 注销/腻子关闭无关。
When you then finally close your putty session, bash receives a "SIGHUP", but doesn't forward it to any other process (since there are no jobs left) In the other case, bash did still have a job left, which it then sent the SIGHUP to, causing it to end (as you noticed)
当您最终关闭您的腻子会话时,bash 会收到一个“SIGHUP”,但不会将其转发给任何其他进程(因为没有剩余的工作)在另一种情况下,bash 确实还有一个工作,然后它将 SIGHUP 发送到,导致它结束(如您所见)
Hope this helps
希望这可以帮助

