zenity --auto-kill: Уничтожение подоболочки не убивает ее дочерние процессы?

Мне очень трудно понять поведение zenity --progress --auto-kill. Похоже, что он не убивает подпроцессы своего родительского процесса, а каким-то образом отсоединяет их.

Рассмотрим следующий сценарий оболочки long-live-the-subshell.sh:

#!/bin/sh
(
    echo sleeping...>&2;
    sleep 5;
    echo woke up >&2 
)  | zenity --progress --auto-close --auto-kill

Чтобы воспроизвести указанное поведение:

  • выполнить скрипт sh long-live-the-subshell.sh
  • нажмите Отмена на индикаторе выполнения.
  • подождите еще 5 секунд
  • увидеть, что woke up выводится на терминал

Пример вывода:

> sh long-live-the-subshell.sh 
sleeping...
Hangup
> woke up

Hangup происходит, когда вы нажимаете Отмена. Затем вы получаете подсказку обратно. Однако после завершения sleep 5 на терминал выводится woke up.

ps jf сразу после запуска скрипта:

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
20806 20825 20825 20825 pts/7     2391 Ss    1000   0:01 -zsh
20825  2391  2391 20825 pts/7     2391 S+    1000   0:00  \_ sh test.sh
 2391  2392  2391 20825 pts/7     2391 S+    1000   0:00      \_ sh test.sh
 2392  2394  2391 20825 pts/7     2391 S+    1000   0:00      |   \_ sleep 5
 2391  2393  2391 20825 pts/7     2391 Sl+   1000   0:00      \_ zenity --progress --auto-close --auto-kill

ps jf сразу после нажатия Отмена:

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 1179  2392  2391 20825 pts/7    20825 S     1000   0:00 sh test.sh
 2392  2394  2391 20825 pts/7    20825 S     1000   0:00  \_ sleep 5

По-видимому, zenity убивает свой PPID (в данном случае 2391), но каким-то образом оба других потомка 2391 (2392 и его единственная дочерняя команда sleep 2394) остаются в живых. Почему? Не должен ли kill -1 2391 (что, очевидно, что делает zenity) убить также детей 2391?


person NobodyInPerson    schedule 17.06.2017    source источник
comment
Что произойдет, если вместо этого вы превратите подоболочку в составной оператор, то есть { echo...; sleep ...; echo ...; } | zenity...   -  person Mark Setchell    schedule 17.06.2017
comment
@MarkSetchell Если я поменяю круглые скобки на фигурные, поведение будет таким же. woke up по-прежнему выводится на терминал.   -  person NobodyInPerson    schedule 18.06.2017
comment
Неужели никто в этом не разбирается? :-О   -  person NobodyInPerson    schedule 26.08.2017
comment
Это может помочь... bernaerts.dyndns. орг/линукс/   -  person Mark Setchell    schedule 26.08.2017


Ответы (1)


Я только что нашел хороший способ, который работает для меня, и я думаю, что он должен работать в большинстве случаев, используя bash.

Идея состоит в том, что вы запускаете Zenity в контейнере с ловушкой: когда zenity --auto-kill отправляет SIGHUP родительскому процессу, родительский процесс отправляет SIGHUP всем процессам в той же группе процессов перед смертью. Итак, ключ вызывает Zenity следующим образом:

{
    trap 'pkill -g 0' HUP
    zenity --progress --auto-kill
}

В приведенном ниже коде я показываю, как я использовал это с именованным каналом, питающим Zenity, что упрощает задачу, если вы хотите, чтобы запущенный процесс выдавал данные на стандартный вывод.

#! /bin/bash

...

zenityfifo=/tmp/zenityfifo$$
trap "rm --force $zenityfifo" EXIT

if [ -x /usr/bin/zenity -a "$DISPLAY" ]; then
    rm --force $zenityfifo
    mkfifo $zenityfifo
    ## The while loop is needed to keep the pipe blocking on read
    while read p < $zenityfifo; do echo $p; done | {
    trap 'pkill -g 0' HUP
    zenity --progress --title="resync" --auto-close --auto-kill
    } &
fi

while ...; do
    ...
    echo ... > $zenityfifo
done
person user2987821    schedule 26.06.2020