Скрипт, вызванный с помощью nohup, иногда завершает работу при выходе из вызывающего скрипта

Так и должно быть:

<my_cmd> 2>file3 | tee file1 file2 > /dev/null

Сначала выполняется перенаправление stderr, а затем teeполучает только stdout.

2
02.04.2021, 17:01
1 ответ

Вероятно, проблема заключается в том, что процесс, разветвленный screenshot-menu.bashдля выполнения nohup./screenshot.bash -$keyв фоновом режиме, получает SIGHUPи завершается до того, как nohupсможет запуститься.

Простой эксперимент, кажется, подтверждает это:

$ alacritty -e sh -c 'nohup sleep 1000 &'
$ pgrep -a sleep
$

straceвыполнение всей команды показывает, что shразветвляется, но execveне выполняется nohupдо того, как разветвленный процесс получит SIGHUP— когда alacrittyзавершается и созданный им псевдотерминал -исчезает — и уходит.

Не ища альтернативных подходов (, которые, вероятно, существуют, когда дело доходит до смешивания терминальных и графических приложений ),Логичное решение состоит в том, чтобы не применять nohupк команде, которая переходит в фоновый режим, и вместо этого использовать ее в родительском процессе. Например:

$ alacritty -e sh -c 'nohup sh -c "sleep 1000 &"'
$ pgrep -a sleep
625910 sleep 1000

В screenshot-menu.bashвы можете таким образом изменить эту строку

s|w|r) nohup./screenshot.bash -$key & ;;

в

s|w|r) nohup sh -c "./screenshot.bash \"-$key\" &" ;;

Кроме того, вы можете включить управление заданиями в screenshot-menu.bashс помощью set -mи избавиться отnohup(оболочка запустит фоновые конвейеры (простая команда — это тоже конвейер )в своем собственном процессе групп, и только группа процессов переднего плана доставляется SIGHUP, когда ее управляющий терминал исчезает ), при условии, что вы можете убедиться, что ничто в screenshot.bashне пытается читать или записывать на терминал (, т.е. вам нужно явные перенаправления, эквивалентные выполненнымnohup).

Например, screenshot-menu.bashможет стать:

#!/usr/bin/env bash

set -m

echo 'Select an option:
...
'

case $key in
  s|w|r) </dev/null >>./log.txt 2>&1./screenshot.bash "-$key" & ;;
  *) echo Canceled. >>./log.txt ;;
esac

См. также:

1
28.04.2021, 22:54

Теги

Похожие вопросы