nohup
only make program immune to SIGHUP
and SIGQUIT
signal. Modern shell maybe send other signals when you logout from your session, so there is no guarantee that your program is not killed, even running under nohup
.
The better solution is using tmux
or screen
, or if you use bash
, you can try:
$ java -jar project.jar &
$ disown
When you close a GNOME Terminal window, a SIGHUP is sent to the shell that it was running. The shell will typically send a SIGHUP to every process group that it knows it created - even ones started with nohup
- and then exit. If the shell is bash
, it will skip sending a SIGHUP to any process group that the user marked with disown
.
Running a command with nohup
makes it ignore SIGHUP, but the process can change that. When the disposition of SIGHUP for a process is the default, then if it receives a SIGHUP, the process will be terminated.
Linux provides some tools to examine a running process's signal settings.
The chromium-browser shell script does an exec
of the compiled app, so its process ID remains the same. So to see its signal settings, I ran nohup chromium-browser &
and then looked at /proc/$!/status
to see the signal disposition.
SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000180014003
Those are hex numbers. This shows that SIGHUP is not caught and is not ignored. Only SIGPIPE (the 13th bit in SigIgn) is ignored. I traced this to the following code:
// Setup signal-handling state: resanitize most signals, ignore SIGPIPE.
void SetupSignalHandlers() {
// Sanitise our signal handling state. Signals that were ignored by our
// parent will also be ignored by us. We also inherit our parent's sigmask.
sigset_t empty_signal_set;
CHECK(0 == sigemptyset(&empty_signal_set));
CHECK(0 == sigprocmask(SIG_SETMASK, &empty_signal_set, NULL));
struct sigaction sigact;
memset(&sigact, 0, sizeof(sigact));
sigact.sa_handler = SIG_DFL;
static const int signals_to_reset[] =
{SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV,
SIGALRM, SIGTERM, SIGCHLD, SIGBUS, SIGTRAP}; // SIGPIPE is set below.
for (unsigned i = 0; i < arraysize(signals_to_reset); i++) {
CHECK(0 == sigaction(signals_to_reset[i], &sigact, NULL));
}
// Always ignore SIGPIPE. We check the return value of write().
CHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR);
}
Despite the comment, signals ignored by the parent are not being ignored. A SIGHUP will kill chromium.
The workaround is to do what @xx4h points out: use the disown
command in your bash so that, if bash has to exit, it does not send SIGHUP to the chromium-browser
process group. You can write a function to do this:
mychromium () { /usr/bin/chromium-browser & disown $!; }
Best Answer
As far as I know, there are two situations that can cause a process to be killed after being protected by
nohup
, and each situation has a different workaround.One possibility, which does not appear to be the case here, is that the system uses systemd where
logind.conf
is configured withKillUserProcesses=yes
. In this case, closing the terminal will not cause problems, but logging out of the system will. The workaround in this case is to useThis basically just tells systemd that it should not kill the process.
The other possibility is that the spawned process implements its own handler for
SIGHUP
which overrides the protection ofnohup
. In this case, problems will occur as soon as the shell is closed, even if you remain logged in. You can check for this with:You should see a line
(or some other string of hexadecimal digits).
SIGHUP
is signal number1
, so if this big-endian hexadecimal number has its first (least-significant) bit set (that is, the final digit is one of 1, 3, 5, 7, 9, B, D, or F), thenSIGHUP
is ignored. Otherwise, the program has installed its own handler overriding the protection ofnohup
.In this case, the solution is to use
disown
:This removes the process from the shell's job list, preventing
SIGHUP
from being sent in the first place.