Processo morto antes de ser lançado em segundo plano

5

Estou usando um script bash script.sh contendo um comando cmd , lançado em segundo plano:

#!/bin/bash
…
cmd &
…

Se eu abrir um emulador de terminal e executar script.sh , cmd será executado corretamente em segundo plano, como esperado. Ou seja, enquanto script.sh terminou, cmd continua sendo executado em segundo plano, com o PPID 1.

Mas, se eu abrir outro emulador de terminal (digamos xfce4-terminal) do anterior (ou no início da sessão de desktop, que é o meu caso de uso real), e execute script.sh by

xfce4-terminal -H -x script.sh

cmd não é mais executado corretamente: é eliminado pelo término de script.sh . Usando nohup para evitar isso não é suficiente. Eu sou obrigado a colocar um comando sleep após ele, caso contrário, cmd é morto pela terminação de script.sh , antes de ser dissociado dele.

A única maneira que eu encontrei para fazer cmd executar corretamente em segundo plano é colocar set -m em script.sh . Por que é necessário neste caso, e não no primeiro? Por que essa diferença de comportamento entre as duas formas de executar script.sh (e, portanto, cmd )?

Eu assumo que, no primeiro caso, o modo monitor não está ativado, como se pode ver colocando set -o em script.sh .

    
por Glyph 10.11.2018 / 12:47

2 respostas

3

O processo em que o cmd deve ser executado será eliminado pelo sinal SIGHUP entre o fork () e o exec (), e qualquer wrapper nohup ou outro material não terá chance de ser executado e ter qualquer efeito. (Você pode verificar isso com strace )

Em vez de nohup , você deve definir SIGHUP para SIG_IGN (ignore) no shell pai antes de executar o comando background; Se um manipulador de sinal estiver definido como 'ignore' ou 'default', essa disposição será herdada através de fork () e exec (). Exemplo:

#! /bin/sh
trap '' HUP    # ignore SIGHUP
xclock &
trap - HUP     # back to default

Ou:

#! /bin/sh
(trap '' HUP; xclock &)

Se você executar este script com xfce4-terminal -H -x script.sh , o comando de segundo plano ( xclock & ) não será eliminado pelo SIGHUP enviado quando script.sh terminar.

Quando um líder de sessão (um processo que "possui" o terminal de controle, script.sh no seu caso) terminar, o kernel enviará um SIGHUP para todos os processos de seu grupo de processos foreground ; mas set -m ativará o controle de tarefas e os comandos iniciados com & serão colocados em um grupo de processos background , e eles não serão sinalizados por SIGHUP .

Se o controle de trabalho não estiver ativado (o padrão para um script não interativo), os comandos iniciados com & serão executados no mesmo grupo de processos primeiro plano e o modo "segundo plano" ser falsificado por redirecionando sua entrada de /dev/null e permitindo que eles ignore SIGINT e SIGQUIT .

Processos iniciados dessa maneira a partir de um script que, uma vez executado como um trabalho em primeiro plano, mas que já tenha saído, não serão sinalizados com SIGHUP , pois o grupo de processos (herdado do pai morto) não é mais o primeiro plano no terminal.

Notas extras:

O 'modo hold' parece ser diferente entre xterm e xfce4-terminal (e provavelmente outros terminais baseados em vte). Enquanto o primeiro manterá o lado mestre do arquivo aberto, este último irá separá-lo depois que o programa rodar com -e ou -x tenha saído, fazendo com que qualquer gravação no lado escravo falhe com EIO . xterm também ignorará WM_DELETE_WINDOW mensagens (isto é, não fechará) enquanto ainda houver processos do grupo de processos em primeiro plano em execução.

    
por 11.11.2018 / 02:05
0

Eu tenho jogado com isso. Eu não consigo entender, mas aqui está o que eu descobri. Eu usei o sono 3 como meu cmd.

Estes dois trabalhos. Não tenho ideia do que faz o ls no final. Os colchetes e duplo nohup , bem eles fazem um subprocesso (acho que é assim que nohup funciona). Não faço ideia do porquê nohup por si só não funciona.

#!/bin/bash

nohup nohup sleep 3 &
ls #no idea why I need this

e

#!/bin/bash

(
nohup sleep 3 &
ls #no idea why I need this
)

/bin/true funciona no lugar de ls . Parece que precisamos chamar um comando externo. Ainda não faço ideia do porquê.

    
por 10.11.2018 / 15:20