13

I issued the ^z; bg; disown sequence in order to allow me to close an ssh session in which I am running a super-important long-running process. This process writes status output to stderr, and it has continued to do so even after being detached (verified with lsof, the stderr fd is open for r/w).

Is there a way to determine that the process has indeed been disowned (will not recv SIGHUP if the shell recvs one)?

2
  • 1
    I wonder if this needs to go to unix.stackexchange.com
    – Rilindo
    Dec 1, 2011 at 21:49
  • 2
    Just curious, why not: $PROCESS 1>>/root/std.out 2>>/root/err.out & Dec 1, 2011 at 21:54

2 Answers 2

14

In Bash, the disown command issued by itself will remove backgrounded (via bg or &) processes from the active job table, and mark them to not receive a SIGHUP on logout.

You can also pass one or more jobs to disown, like disown 1 3. The disown -h flag is useful if you want to keep jobs in the table, but still not SIGHUP on logout.

You can view the job table by issuing the jobs command. After a successful background, it will show [1]+ command &. After disowning a job, it should no longer display in the job table, and no longer be killed on logout. You can still view the process via ps ux, top, and other process-viewing utilities.

After a job has been disowned, you can wait for it to terminate naturally or send a signal via kill to the PID to stop it.

Because Bash is just removing the job from the list of running jobs to terminate and the file handles to your terminal's stdout and stderr are still open, you will continue to receive output from the job until your terminal device is closed (when you log out).

Examples:

# we start a command in the background
$ cat /dev/urandom > test &
[1] 18533

# we see our command is still running
$ jobs
[1]+  Running                 cat /dev/urandom > test &

# we disown the backgrounded job
$ disown 1

# notice it is no longer in the job table
$ jobs

I usually only use disown if I run a potentially long-running command like a rsync or cp and afterwards decide I need to log out without terminating it. If you know you're going to run a command and log out, you can capture the output by piping or teeing it to a file, running it with nohup, or running it in screen (which allows you to retake ownership of the command/terminate afterwards).

Examples:

# capture stdout and stderr to separate logs
cat /dev/urandom >stdout.log 2>stderr.log

# capture stdout and stderr to the same log, and display to stdout as well
cat /dev/urandom 2>&1 | tee output.log

# run a command under nohup (doesn't require a disown or job control support)
nohup cat /dev/urandom </dev/null
4
  • 1
    +1 Informative and with examples. Nice!
    – Andy Smith
    Dec 2, 2011 at 0:55
  • Very informative comment; are you saying that it is not possible to verify a process's detachment (besides noting that it no longer exists in the jobs table)?
    – mikewaters
    Dec 2, 2011 at 12:17
  • 1
    when you run detach on a backgrounded job, it's going to be detached :) there's not really a middle ground there where running it on a backgrounded process will do nothing. checking jobs just verifies you didn't try to detach a stopped process or something.
    – lunixbochs
    Dec 2, 2011 at 13:36
  • 1
    Is it possible to verify if disown -h is already set for a job?
    – mgutt
    Aug 28, 2022 at 20:47
0

Is there a way to determine that the process has indeed been disowned (will not recv SIGHUP if the shell recvs one)?

If you have the shell that the command was originally invoked in still open, then you can use jobs as @lunixbochs mentioned to verify the process no longer shows.

If you have already closed the shell then you should see that the parent PID (PPID) changes from the parent process to 1 (the init PID). I normally verify this with ps -elf | grep <command>

e.g.

➜  ~ sleep infinity
^Z
[1]  + 3202480 suspended  sleep infinity

➜  ~ bg
[1]  + 3202480 continued  sleep infinity

➜  ~ ps -elf | grep sleep
0 S user    3202480 1585476  0  80   0 -  1369 ia32_s 18:23 pts/1    00:00:00 sleep infinity

➜  ~ jobs
[1]  + running    sleep infinity

➜  ~ disown %1

➜  ~ jobs

now kill the parent shell and look at the PPID (notice it is now 1):

➜  ~ ps -elf | grep sleep
0 S user    3202480 1  0  80   0 -  1369 ia32_s 18:23 pts/1    00:00:00 sleep infinity

to kill the job run:

kill -9 <PID>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .