如何强制程序在前台运行

如何强制程序在前台运行

有一个程序会自动守护进程并在后台运行。

有没有办法强制这个程序在前台运行?我想把它放在一个脚本中,然后捕获返回码,看看它是否正常退出。

答案1

当进程守护进程时,它会分叉自身(至少一次),父进程立即返回,子进程完成工作。

当那个孩子死后,它就不再有父母了。或者更确切地说,它已被init(id 1 的进程)采用。init将能够获得其退出状态。

在 Linux 上,自内核 3.4 起,您可以使用以下命令更改哪个进程将采用孤儿进程(为其子进程和后代进程)PR_SET_CHILD_SUBREAPER prctl()

所以就像在这个非常相似的问答,如果在 Linux 3.4+ 上,您可以在一个自称是儿童副收割者并让它报告其孤儿后代的退出状态:

这里使用perl并硬编码 的值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

答案2

假设这只是为了偶尔的调试,如果你只是想捕获退出代码,那么如果你知道最终守护进程的进程 ID,你可以使用 附加到它,strace -p这样跟踪直到它退出。

例如,如果您在退出之前没有时间获取 pid,则可以运行下面的命令strace -f并跟踪子进程。我没有任何简单的守护进程演示,但您可以通过以下示例了解它如何工作:

$ 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 +++

在这里我们可以看到我们成功地从内部“守护进程”bash 命令中收集了 2 的退出代码。


或者,如果您有系统,您可以运行尝试在单独的 cgroup 中运行该命令:

$ systemd-run --user --service-type=forking  bash -c '(sleep 99;exit 2)& exit 0'
Running as unit run-8772.service.

除了轮询之外,我不知道如何收集生成的退出代码。如果完成得太快,守护进程仍然处于活动状态:

$ 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

经过适当的延迟后,进程就会终止,我们可以访问所需的退出代码:

$ 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)

相关内容