Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I was helping a colleague who was having problems with a background process intermittently dying.

I found out that they were starting the background process by logging in to the server and executing:

su - <user> -c '<command>' &

"Aha", I exclaimed. "If you start a command with "&" it will hang-up when you exit the controlling terminal. You need to use something like nohup to achieve this. Really this process needs to support running as a daemon, tut tut."

We tested the above command to demonstrate my point and... it seemed to work: the process started by command didn't exit when the we exited the terminal that ran the above command.

command is a custom Python script whose output goes to a file. As far as I can tell there is no intelligent "daemonize" like capability in the script. It doesn't do any of the things needed to run as a daemon listed here 1

Running the command like so behaves as expected:

<command> &
exit

In the above case the background process started by command exits when we exit the terminal.

My question is this:

  1. What is happening when we add "su - -c &" that prevents the process from exiting when our terminal exits. I would like to understand in detail with respect to the controlling terminal, standard input and output etc.

  2. Is this a reasonable way to achieve the goal of running this command as a background process. If not why, not?

I want to propagate best practice within my company, but I need to be able to demonstrate and back-up any recommendations I make.

Also, I just want to understand what is going on exactly.

share|improve this question
add comment

1 Answer

There are several ways a process might be killed because of a dying terminal.

  1. The first way is that the terminal driver in the kernel sends a SIGHUP signal to the controlling process for which the terminal is the controlling terminal. In most cases, the controlling process is the shell that is initially started in the terminal, and its controlling terminal is the one that its stdin, stdout and stderr are connected to. A process becomes disconnected from the controlling terminal if it calls setsid.

  2. The second way is that the shell, when it receives SIGHUP, re-sends that signal to its subprocesses — more precisely, to its background jobs. Some shells (ksh, bash, zsh) have a disown builtin to tell the shell not to send a SIGHUP to a particular job.

  3. If the terminal goes away and a program tries to read from it, it is notified of an end-of-file condition (or possibly EIO for a background job). If the terminal goes away and a program tries to write to it, the write returns with an EIO error. These might cause the program to exit.

So what su changes here is that (2) would normally cause the initial shell to kill the background job, but since that background process is running as a different user, the signal cannot be delivered, and the background process lives on.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.