Может $! вызвать условия гонки при использовании в скриптах, работающих параллельно?

8

Скажем, у меня есть несколько сценариев bash, которые работают параллельно, с кодом, подобным следующему:

#!/bin/bash

tail -f /dev/null &
echo "pid is "$!

Является ли $!гарантированно дать мне PID в самой последней фоновой задачи в этом сценарии , или это самая последняя фоновая задача во всем мире? Мне просто любопытно, может ли использование этой функции вызвать состояние гонки, когда возвращаемый PID определяется процессом, запущенным в другом сценарии.

philraj
источник

Ответы:

16

$!гарантированно даст вам pid процесса, в котором оболочка выполнила эту tailкоманду. Оболочки являются однопоточными, каждая оболочка живет в своем собственном процессе со своим набором переменных. Там нет никакого способа , $!из одной оболочки будет течь в другую оболочку, так же , как и присваивание переменной оболочки в одной оболочке не будет влиять на переменную с тем же именем в другой оболочке (если оставить в стороне универсальных переменных на fishоболочке) ,

Теперь, tail -f /dev/nullэто команда, которая выполняется бесконечно, но для кратковременных команд, обратите внимание, что, поскольку существует ограниченное число возможных идентификаторов процессов, идентификаторы процессов неизбежно заканчиваются тем, что будут повторно использованы.

В:

true &
pid=$!

Он $pidбудет содержать идентификатор процесса, в котором запускалась оболочка true, но к тому времени, когда вы его используете $pid, этот pid может быть уже мертв и может ссылаться на другой процесс.

Стефан Шазелас
источник
3
Да, я знал о вашем втором замечании, и если вы хотите создать надежного менеджера фоновых процессов, вам нужно использовать язык, который гарантирует, что вы будете знать точный момент, когда дочерний процесс завершился и его PID был возвращен в пул , что, очевидно, не могут сценарии оболочки, поскольку они агрессивно пожинают дочерние процессы. Спасибо за четкое объяснение.
Philraj
5
@philraj, в zsh вы можете установить обработчики на SIGCHLD, которые обрабатываются после завершения асинхронных заданий и используются $jobstate/$jobtextдля проверки там состояния процесса. Не без гонки, так как ребенок уже пожинает плоды во время выполнения ловушки, но это означает, что очень короткие гоночные окна, где очень маловероятно, что пидс будут повторно использованы.
Стефан