当我退出shell时,为什么unix后台进程有时会死?

时间:2009-09-23 03:46:39

标签: bash unix putty csh nohup

我想知道为什么我在Bash shell中的后台进程中看到了不同的行为

案例1:使用Putty(SSH)

登录Unix服务器
  • 默认使用csh shell
  • 我改为bash shell
  • 打字睡眠2000&
  • 按enter

它给了我工作号码。现在我通过点击putty窗口中的x来杀死我的会话 现在打开另一个会话并尝试查找该过程。该过程已经死亡。

案例2:案例1:使用Putty(SSH)登录Unix服务器 默认情况下,它使用csh shell

  • 我改为bash shell
  • vi mysleep.sh
  • sleep 2000&保存了mysleep.sh
  • ./ mysleep.sh

这里的差异是......而不是直接执行sleep命令我将sleep命令存储在文件中并执行文件。

现在我通过点击putty窗口中的x来杀死我的会话 现在打开另一个会话并尝试查找该过程。该过程仍在那里

不确定为什么会这样。我认为我需要在bash中使用,以便在注销后运行该过程。

我在父进程id中看到一个差异。在第二种情况下,sleep 2000的父进程id变为1.看起来只要mysleep.sh的进程死了,内核就将父进程分配给1

4 个答案:

答案 0 :(得分:20)

这里的差异确实是干预过程。 当您关闭终端窗口时,会向其中运行的进程发送HUP信号(与“nohup”相关,如提到的a0nymo0usc0ward)。接收HUP的默认操作是死 - 来自signal(3)联机帮助页,

 No    Name         Default Action       Description
 1     SIGHUP       terminate process    terminal line hangup

在您的第一个示例中,睡眠过程直接接收此HUP信号并死亡,因为它未设置为执行任何其他操作。 (某些进程捕获HUP并使用它来执行某些操作,例如重新读取一些配置文件)

在第二个示例中,运行shell脚本的shell进程已经死亡,因此睡眠过程永远不会获取信号。在UNIX中,由于wait(2)系列调用的工作原理以及一般的处理过程,每个进程都必须有一个父进程。因此,当父进程终止时,内核会将其作为寄养子项提供给init(pid 1,如您所述)。 Orphan process (on wikipedia)提供了更多相关信息,另请参阅Zombie process了解其他一些技术细节。

答案 1 :(得分:8)

已经在运行过程?

^ Z
BG
disown%<jobid>

新进程/脚本(在本地计算机的控制台上)?

nohup script.sh&amp;

新进程/脚本(在远程计算机的控制台上)?

根据您的需要,
有两种选择[会有更多;-)]

ssh remotehost'nohup /path/to/script.sh </dev/null&gt; nohup.out 2&gt;&amp; 1&amp;'

OR

使用'screen'

答案 2 :(得分:3)

尝试“nohup cmd args ...”

答案 3 :(得分:0)

史蒂文的回答是正确的,但我想再次强调一下棘手的部分:

=&GT;使用只在后台执行sleep的bash脚本

这样做的结果是“脚本”几乎立即退出(因为它完成了所有命令)。但是,它确实在其生命周期中创建了一个子进程(sleep)。这样做的结果是:

  • “脚本”不能再是父母了,睡眠是孤儿的(在pstree中很好地显示)
  • 您启动脚本的bash shell不再有基础作业

请注意,这些内容都是在您执行脚本时发生的,并且与任何ssh logout / putty关闭无关。

当你最后关闭你的putty会话时,bash会收到一个“SIGHUP”,但不会将它转发到任何其他进程(因为没有剩余的工作) 在另一种情况下,bash仍然有一个工作,然后它发送SIGHUP,导致它结束(如你所注意到的)

希望这有帮助