简体   繁体   English

在BASHRC和命令行中启动后台进程之间的区别

[英]Difference between starting a background process in BASHRC vs Command Line

I am trying to background a process automatically. 我正在尝试自动后台处理进程。

nohup program > /tmp/program.log 2>&1 < /dev/null &
disown

If I check if the process is running and start it on login via ".bashrc", the program starts but then DIES when I exit. 如果我检查进程是否正在运行,并通过“ .bashrc”在登录时启动它,则程序将启动,但退出时会死掉。

BUT if I do exactly the same command on the command line, the program continues to run, in background, when I exit. 但是,如果我在命令行上执行完全相同的命令,则退出时该程序将继续在后台运行。

I can't find any difference in program environment between a bashrc start and a cli start. 我找不到bashrc启动和cli启动之间的程序环境差异。 (The bashrc has almost nothing in it). (bashrc中几乎没有任何内容)。 My understanding the program in both cases should be treated the same. 我对这两种情况下的程序的理解应该相同。

What is the difference, and how can I stop a bashrc started 'daemon' being killed when the shell exits. 有什么区别,以及如何在退出外壳时阻止bashrc启动的“守护程序”被杀死。

PS: removing nohup makes no difference. PS:删除nohup没什么区别。 and I have watched the program running then dying from a separate login, when the starting login exits. 并且我已经看到程序运行,然后在退出初始登录时从另一个登录中消失。

And before someone says anything... Adding "disown" after backgrounding the program in the bashrc did NOT fix it! 在某人说什么之前...在bashrc中使该程序后台运行后添加“ disown”并不能解决问题!

UPDATE: If the ssh login connection is killed (window closed or connection terminated suddenly) the program started in the bashrc continues to run, but that seems to be because the bash that started it is also still running (at least for the time being). 更新:如果ssh登录连接被终止(窗口关闭或连接突然终止),则在bashrc中启动的程序将继续运行,但这似乎是因为启动它的bash仍在运行(至少暂时如此) 。 The background is only killed if you type "exit" for the bash, or the bash is killed (even with a untrappable signal 9!). 仅当您为bash键入“ exit”或杀死bash(即使信号为9!)时,背景才会被杀死。

The PPID of the program (disowned by the shell) is 0 that is its parent is not the shell NOR the init process! 程序的PPID(由Shell弃用)为0,即其父级不是Shell NOR初始化进程! This the case regardless how it is started. 这种情况无论如何启动。

UPDATE 2... background program started from bashrc... 更新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

I killed that one then started it from command line... 我杀死了那个人,然后从命令行启动了它。

   891    891    891 pts/2    Ss+    0:00 /bin/bash
   958    955    891 pts/2    Sl     0:00 program

Now when the shell exists the program does not exit. 现在,当外壳存在时,程序不会退出。 So it looks like the only different is the PGID changed. 因此,看起来唯一的不同是PGID发生了变化。

How can I start a process in a different PGID? 如何在其他PGID中启动流程?

Process groups are needed for job control, because a shell needs something to send job control signals to, eg when you type fg . 作业控制需要进程组,因为外壳需要一些东西来将作业控制信号发送到,例如,当您键入fg POSIX.1-2017 states POSIX.1-2017 状态

A command interpreter process supporting job control can allocate the terminal to different jobs, or process groups , by placing related processes in a single process group and associating this process group with the terminal 支持作业控制的命令解释器流程可以通过将相关流程置于单个流程组中并将该流程组与终端相关联,从而将终端分配给不同的作业或流程组

(italics are mine) This seems even to equate the concepts of "process group" and "job", although most people use the term "job" for process groups (and even children in the shell's own process group) that are registered in the shells job table (and may be removed from that table by the builtin disown ) (斜体字是我的)这似乎甚至等同于“进程组”和“作业”的概念,尽管大多数人将“作业”一词用于注册在操作系统中的进程组(甚至是外壳程序组中的子级)。外壳作业表 (并且可以通过内置的disown从该表中删除)

So, if a shell doesn't want to start a child command (or even shell pipeline) under job control, it doesnt't create a new process group (by calling setpgrp() ) 因此,如果外壳程序不想在作业控制下启动子命令(甚至外壳程序管道),则不会创建新的进程组(通过调用setpgrp()

This happens eg when using process substitution 发生这种情况,例如在使用流程替代时

blah=$(sleep 1000 | sleep 1000)

(try it, and have a look at the output of ps -jA w !) and, apparently, when starting commands from .bashrc (尝试一下,看看ps -jA w的输出!),显然是从.bashrc启动命令时

nohup <command> , by itself, will not start a new process group, it only ignores SIGHUP and then executes command nohup <command>本身不会启动新的进程组,它只会忽略 SIGHUP ,然后执行command

Linux (and other OS'es when you install something like util-linux ) has a command setsid that will do what you expected (but did not get) from nohup : setsid command will create a new process group for <command> and make it the session leader of a new session. Linux(以及安装了util-linux类的其他OS)具有命令setid ,该命令可以完成 nohup 预期的操作 (但没有得到): setsid command将为<command> 创建一个新的进程组并使其生效新会议的会议负责人。 The PGID of this new process group will be unknown to the caller ( bash in this case) so we don't need to use nohup anymore. 该新进程组的PGID对于调用者而言将是未知的(在本例中为bash ),因此我们不再需要使用nohup

So, use setsid instead of nohup and you're done (I only now see Mark Plotnick's comment, which is right on the money. Oh well, I hope my answer also clarifies the reason why setsid is the better alternative in this case) 因此,使用setsid代替nohup ,您就完成了(我现在只看到Mark Plotnick的评论,这对您来说是对的。哦,好吧,我希望我的回答也能阐明在这种情况下setsid是更好的选择的原因

Okay... it seems the problem was actually being caused by the environment. 好吧...看来问题实际上是由环境引起的。

The shell was being run in a docker container. 该外壳程序正在docker容器中运行。 and it seems Docker Exec is the one terminating all processes in the same Process Group, not the shell. 似乎Docker Exec是终止同一进程组中所有进程的终端,而不是Shell。 Or at least that appears to be the case. 或者至少看起来是这样。

However I still find it weird that a program backgrounded from ".bashrc" inherits the same process group as the parent shell, BUT exactly the same backgrounding command from the command line gets its own seperate process group. 但是,我仍然感到奇怪的是,以“ .bashrc”为背景的程序继承了与父外壳程序相同的进程组,但是从命令行获得的完全相同的后台命令却获得了自己的单独进程组。

Once I discovered this was the cause, I discovered process groups was mentioned in the BASH manpage, with regard to Backgrounding a process, though it makes no mention of the difference starting it in the ".bashrc" vs CLI. 一旦找到了原因,就发现在BASH联机帮助页中提到了有关进程后台的过程组,尽管它没有提及“ .bashrc”与CLI的区别。

Every bash process has a PPID (Parent PID) 每个bash进程都有一个PPID(父PID)

If you run the following from terminal: 如果从终端运行以下命令:

nohup tail -f /dev/null > /tmp/rand.txt &

The PPID from ps -ef output shows the PPID is init (First process to start): 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

If you run the same command from bashrc the PPID is the bash process: 如果从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

When running from terminal the process will continue until init is stopped. 从终端运行时,该过程将继续进行,直到停止初始化为止。

When running from bashrc the process will continue until bash is stopped. 从bashrc运行时,该过程将继续直到bash停止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM