Como forçar um programa a ser executado em primeiro plano

2

Existe um programa que se daemoniza automaticamente e é executado em segundo plano.

Existe uma maneira de forçar este programa a ser executado em primeiro plano? Eu quero colocá-lo em um script e, em seguida, capturar o código de retorno para ver se ele saiu normalmente ou não.

    
por LINUX G33NYUS 29.03.2017 / 01:00

2 respostas

3

Quando um processo daemoniza, ele se bifurca (pelo menos uma vez), o pai retorna imediatamente e o filho faz o trabalho.

Quando essa criança morre, ela não tem mais um pai. Ou melhor, foi adotado por init (o processo de id 1). init poderá obter seu status de saída.

No Linux, e desde o kernel 3.4, você pode alterar qual processo adotará os processos órfãos (para seus filhos e descendentes) usando o PR_SET_CHILD_SUBREAPER prctl() .

Então, como este Q & A muito semelhante, se no Linux 3.4+, você pode iniciar seu daemon sob um wrapper que se auto-denomina filho subreactor e fazer com que ele relate o status de saída de seus descendentes órfãos:

Aqui, usando perl e codificando o valor da 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
    
por 29.03.2017 / 22:03
1

Supondo que isso seja apenas para a depuração ocasional, se você quiser apenas capturar o código de saída, se souber o ID do processo do processo daemonised final, poderá anexar a ele com strace -p e rastreá-lo até sair.

Se, por exemplo, você não tiver tempo de obter o pid antes de sair, poderá executar o comando em strace -f e, assim, seguir o processo filho. Eu não tenho nenhum deemon de daemon fácil, mas você pode ver como isso funciona com o seguinte exemplo:

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

Aqui podemos ver que conseguimos reunir o código de saída 2 do comando bash "daemonizado" interno.

Alternativamente, se você tiver systemd , você pode rodar o comando try em um cgroup separado:

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

Eu não sei como coletar o código de saída resultante, exceto por polling. Quando feito muito em breve, o daemon ainda está ativo:

$ 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

Após um atraso adequado, o processo está inativo e temos acesso ao código de saída desejado:

$ 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)
    
por 29.03.2017 / 19:13