![](/img/trans.png)
[英]Difference between a service and a process which is running in a background by & command
[英]Difference between starting a background process in BASHRC vs Command Line
我正在尝试自动后台处理进程。
nohup program > /tmp/program.log 2>&1 < /dev/null &
disown
如果我检查进程是否正在运行,并通过“ .bashrc”在登录时启动它,则程序将启动,但退出时会死掉。
但是,如果我在命令行上执行完全相同的命令,则退出时该程序将继续在后台运行。
我找不到bashrc启动和cli启动之间的程序环境差异。 (bashrc中几乎没有任何内容)。 我对这两种情况下的程序的理解应该相同。
有什么区别,以及如何在退出外壳时阻止bashrc启动的“守护程序”被杀死。
PS:删除nohup没什么区别。 并且我已经看到程序运行,然后在退出初始登录时从另一个登录中消失。
在某人说什么之前...在bashrc中使该程序后台运行后添加“ disown”并不能解决问题!
更新:如果ssh登录连接被终止(窗口关闭或连接突然终止),则在bashrc中启动的程序将继续运行,但这似乎是因为启动它的bash仍在运行(至少暂时如此) 。 仅当您为bash键入“ exit”或杀死bash(即使信号为9!)时,背景才会被杀死。
程序的PPID(由Shell弃用)为0,即其父级不是Shell NOR初始化进程! 这种情况无论如何启动。
更新2 ...后台程序从bashrc启动...
# ps -jA w
PID PGID SID TTY STAT TIME COMMAND
891 891 891 pts/2 Ss+ 0:00 /bin/bash
899 891 891 pts/2 Sl+ 0:00 program
我杀死了那个人,然后从命令行启动了它。
891 891 891 pts/2 Ss+ 0:00 /bin/bash
958 955 891 pts/2 Sl 0:00 program
现在,当外壳存在时,程序不会退出。 因此,看起来唯一的不同是PGID发生了变化。
如何在其他PGID中启动流程?
作业控制需要进程组,因为外壳需要一些东西来将作业控制信号发送到,例如,当您键入fg
。 POSIX.1-2017 状态
支持作业控制的命令解释器流程可以通过将相关流程置于单个流程组中并将该流程组与终端相关联,从而将终端分配给不同的作业或流程组
(斜体字是我的)这似乎甚至等同于“进程组”和“作业”的概念,尽管大多数人将“作业”一词用于注册在操作系统中的进程组(甚至是外壳程序组中的子级)。外壳作业表 (并且可以通过内置的disown
从该表中删除)
因此,如果外壳程序不想在作业控制下启动子命令(甚至外壳程序管道),则不会创建新的进程组(通过调用setpgrp()
)
发生这种情况,例如在使用流程替代时
blah=$(sleep 1000 | sleep 1000)
(尝试一下,看看ps -jA w
的输出!),显然是从.bashrc
启动命令时
nohup <command>
本身不会启动新的进程组,它只会忽略 SIGHUP
,然后执行command
Linux(以及安装了util-linux
类的其他OS)具有命令setid ,该命令可以完成 nohup
预期的操作 (但没有得到): setsid command
将为<command>
创建一个新的进程组并使其生效新会议的会议负责人。 该新进程组的PGID
对于调用者而言将是未知的(在本例中为bash
),因此我们不再需要使用nohup
。
因此,使用setsid
代替nohup
,您就完成了(我现在只看到Mark Plotnick的评论,这对您来说是对的。哦,好吧,我希望我的回答也能阐明在这种情况下setsid
是更好的选择的原因 )
好吧...看来问题实际上是由环境引起的。
该外壳程序正在docker容器中运行。 似乎Docker Exec是终止同一进程组中所有进程的终端,而不是Shell。 或者至少看起来是这样。
但是,我仍然感到奇怪的是,以“ .bashrc”为背景的程序继承了与父外壳程序相同的进程组,但是从命令行获得的完全相同的后台命令却获得了自己的单独进程组。
一旦找到了原因,就发现在BASH联机帮助页中提到了有关进程后台的过程组,尽管它没有提及“ .bashrc”与CLI的区别。
每个bash进程都有一个PPID(父PID)
如果从终端运行以下命令:
nohup tail -f /dev/null > /tmp/rand.txt &
ps -ef
输出中的PPID显示PPID是init(首先启动的进程):
UID PID PPID C STIME TTY TIME CMD
user 18424 1 0 16:17 tty1 00:00:00 tail -f /dev/null
如果从bashrc运行相同的命令,则PPID是bash进程:
UID PID PPID C STIME TTY TIME CMD
user 16405 16404 0 Jun20 tty2 00:00:08 bash
user 18424 18386 0 16:17 tty1 00:00:00 tail -f /dev/null
从终端运行时,该过程将继续进行,直到停止初始化为止。
从bashrc运行时,该过程将继续直到bash停止。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.