简体   繁体   中英

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.

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. (The bashrc has almost nothing in it). 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.

PS: removing nohup makes no difference. 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!

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). The background is only killed if you type "exit" for the bash, or the bash is killed (even with a untrappable signal 9!).

The PPID of the program (disowned by the shell) is 0 that is its parent is not the shell NOR the init process! This the case regardless how it is started.

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

How can I start a process in a different PGID?

Process groups are needed for job control, because a shell needs something to send job control signals to, eg when you type fg . POSIX.1-2017 states

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 )

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() )

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

nohup <command> , by itself, will not start a new process group, it only ignores SIGHUP and then executes 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. 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.

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)

Okay... it seems the problem was actually being caused by the environment.

The shell was being run in a docker container. and it seems Docker Exec is the one terminating all processes in the same Process Group, not the 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.

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.

Every bash process has a PPID (Parent 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):

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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