Команда GNU coreutils timeout
чрезвычайно удобна для определенных сценариев, позволяя использовать вывод команды, если она выполняется быстро, и пропускать ее, если это займет слишком много времени.
Как я могу приблизиться к базовому поведению timeout
использования только указанных POSIX утилит?
(Я имею в виду , что может включать в себя комбинацию wait
, sleep
, kill
и кто знает , что еще, но , возможно , я не хватает более легкий подход.)
shell-script
posix
timeout
Wildcard
источник
источник
command & pid=$! ; sleep 5 && kill $pid
command
быстро заканчивается, есть небольшая вероятностьpid
повторного использования другим процессом,kill
запускающимся до запуска команды? Я не хотел бы этого в производственном коде ....timeout
программу и использовать ее?Ответы:
Мой подход будет таким:
Выполнить команду в качестве фонового процесса 1
Выполнить «сторожевой таймер» в качестве фонового процесса 2
Настройте обработчик для перехвата сигнала завершения в родительской оболочке.
Дождитесь завершения обоих процессов. Процесс, который завершается первым, отправляет сигнал завершения родителю.
Обработчик ловушек родителя уничтожает оба фоновых процесса с помощью управления заданиями (один из них уже завершен по определению, но это уничтожение будет безвредным, поскольку мы не используем PID, см. Ниже)
Я попытался обойти возможное состояние гонки, о котором говорится в комментариях, используя идентификаторы управления заданиями оболочки (которые были бы однозначными в этом экземпляре оболочки), чтобы идентифицировать фоновые процессы, которые нужно уничтожить, вместо системных PID.
Результат для
TIMEOUT=10
(команда завершается до сторожевого таймера):Результат для
TIMEOUT=1
(сторожевой таймер останавливается перед командой):Результат для
TIMEOUT=5
(сторожевой таймер и команда завершают работу «почти» одновременно):источник
cleanup() { ...; }
и (b) управление заданиями является функцией bash, не указанной в POSIX (хотя ksh и другие также имеют ее). Хороший сценарий, хотя!timeout="$1"; shift
и(exec "$@"; echo "Command completed"; kill $$)
лучше , чем повторно wordsplitting список аргументов.