How to force a program to run in the foreground
Solution 1
When a process daemonizes, it forks itself (at least once), the parent returns immediately, and the child does the job.
When that child dies, it no longer has a parent. Or rather, it has been adopted by init
(the process of id 1). init
will be able to get its exit status.
On Linux, and since kernel 3.4, you can change which process will adopt the orphan processes (for its children and descendants) using the PR_SET_CHILD_SUBREAPER
prctl()
.
So like in this very similar Q&A, if on Linux 3.4+, you can start your daemon under a wrapper that claims itself a child subreaper and have it report the exit status of its orphan descendants:
Here using perl
and hardcoding the value of the PR_SET_CHILD_SUBREAPER
prctl()
:
perl -MPOSIX -le '
require "syscall.ph";
syscall(&SYS_prctl,36,1) >= 0 or die "cannot set subreaper: $!";
if (!fork) {
exec @ARGV;
exit(127);
}
# now reporting on all children and grand-children:
while (($pid = wait) > 0) {
print "$pid: " . WEXITSTATUS($?)
}' your-daemon here
Solution 2
Assuming this is just for the occasional debug, if you just want to capture the exit code, then if you know the process id of the final daemonised process, you can attach to it with strace -p
and so trace through till its exit.
If, for example, you do not have time to get the pid before it exits you can run the command under strace -f
and so follow the child process. I don't have any easy daemon demos, but you can see how it might work with the following example:
$ strace -f -e exit bash -c 'nohup bash -c "sleep 10; exit 2" &'
strace: Process 9688 attached
[pid 9687] +++ exited with 0 +++
nohup: appending output to 'nohup.out'
strace: Process 9689 attached
[pid 9689] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9689, si_uid=127, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 2 +++
Here we can see we managed to gather the exit code of 2 from the inner "daemonised" bash command.
Alternatively, if you have systemd, you can run try running the command in a separate cgroup:
$ systemd-run --user --service-type=forking bash -c '(sleep 99;exit 2)& exit 0'
Running as unit run-8772.service.
I don't know how to gather the resulting exit code except by polling. When done too soon the daemon is still active:
$ systemctl --user status run-8772
...
Active: active (running) since Wed 2017-03-29 18:56:43 CEST; 14s ago
CGroup: /user.slice/user-1000.slice/[email protected]/run-8772.service
|-8774 /usr/bin/bash -c (sleep 99;exit 2)& exit 0
`-8775 sleep 99
After a suitable delay, the process is dead and we have access to the wanted exit code:
$ systemctl --user status run-8772
Active: failed (Result: exit-code) since Wed 2017-03-29 18:58:22 CEST; 3s ago
Main PID: 8774 (code=exited, status=2)
Related videos on Youtube
LINUX G33NYUS
Updated on September 18, 2022Comments
-
LINUX G33NYUS almost 2 years
There is a program that automatically daemonizes itself and runs in the background.
Is there a way to force this program to run in the foreground? I want to put it in a script and then capture the return code to see whether or not it exited normally.
-
Stéphane Chazelas about 7 yearsSimilar (duplicate?): Get the exit code of processes forked from the master process
-