Bash – How to completely detach a process

bashdisownnohupprocess

I want to spawn a process and run it at the top level so that when the shell exits, the process keeps running.

I had mistakenly thought that nohup would do this, but when I exit from the shell (the shell is a lxc container and I ssh into that) and re-enter, the process is gone.

It seems (looking at pstree) that the process is still under the invoking shell even with nohup or disown.

I tried a few options and setsid seems to work – but am I doing something wrong with nohup here ?

$ cat myproc
sleep 1234

$ myproc &
$ pstree -a | grep -B 3 "1234" | grep -v grep
  |-screen 
  |   |-bash -ls
  |   |   |-bash -ls
  |   |   |   `-sleep 1234


$ nohup myproc &
$ pstree 
  |-screen 
  |   |-bash -ls
  |   |   |-pstree -a
  |   |   `-sh ./myproc
  |   |       `-sleep 1234

$ myproc &
$ disown $!
$ pstree -a | grep -B 3 "1234" | grep -v grep
  |-screen 
  |   |-bash -ls
  |   |   |-bash -ls
  |   |   |   `-sleep 1234

$ setsid myproc &
  |-sh ./myproc
  |   `-sleep 1234

success. But why did nohup not achieve the same? Is there a way to use nohup more correctly?

Best Answer

It's a little hard to diagnose, as you don't give source for myproc, but I suspect that your problem has something to do with "controlling TTY". I wrote a small shell script that just calls sleep 100. I ran it under nohup:

$ nohup ./sleeper > sleeper.out &

[1] 25305
-bash-3.2$ jobs
[1]+  Running                 nohup ./sleeper > sleeper.out &
-bash-3.2$ ps -l -p 25305
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S 429624 25305 18252  0 77   0 - 15961 wait   pts/0    00:00:00 sleeper

If you look at the ps output, you see a column named "TTY". At least some versions of nohup (the one I used above is from GNU coreutils, version 5.97, so relatively old). When I exited the bash shell from which I started sleeper, the TTY column changed to '?', meaning that sleeper didn't have one.

If myproc doesn't deliberately detach itself from it's controlling TTY, it's still possible to get things like a SIGPIPE signal if it tries to write to stdout. It seems to me other things are possible, but I can't recall or google anything up.

If you can find or compile "daemonize", you might want to try it. If myproc is compiled, you could modify the source to call the daemon(3) library function.