Почему стадо bash не выходит с тайм-аутом, если ему не удается получить блокировку?

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

Я использую этот тестовый код:

( ( flock -x 200 ;  sleep 10 ; echo "original finished" ; ) 200>./test.lock ) &
( sleep 2 ; ( flock -x -w 2 200 ; echo "a finished" ) 200>./test.lock ) &

Я запускаю 2 подоболочки (в фоновом режиме). Синтаксис (flock NUM; ...) NUM>FILE взят из справочной страницы flock.

Я ожидаю, что первая подоболочка получит эксклюзивную блокировку на test.lock, затем подождет 10 секунд, затем напечатает «оригинал готов», все время удерживая блокировку. Вторая подоболочка запустится примерно в то же время, подождите 2 секунды, затем попытайтесь получить блокировку test.lock, но тайм-аут через 2 секунды. Если он получит блокировку, он напечатает «готово». Если он не получает блокировку, эта подоболочка должна остановиться, и ничего не должно быть напечатано.

Поскольку первая подоболочка ожидает дольше, она будет удерживать блокировку в течение 10 секунд, поэтому вторая подоболочка не должна получить блокировку и не должна завершиться. т. е. должно быть напечатано "исходное завершенное", а не то и другое.

Что на самом деле происходит, так это то, что печатается «готовый», а затем печатается «исходный готовый».

Это означает, что вторая подоболочка либо (а) не использует ту же блокировку, что и первая подоболочка, либо (б) не может получить блокировку, но продолжает выполняться, либо (в) что-то еще.

Почему эти замки не работают так, как я ожидаю?


person Rory    schedule 24.05.2010    source источник
comment
flock не является командой Bash. Это отдельная программа.   -  person Dennis Williamson    schedule 24.05.2010


Ответы (1)


Проблема в том, что если процессу flock не удается получить блокировку в течение тайм-аута, он не может убить родительский процесс (т. е. оболочку, которая его породила) — все, что он может сделать, это вернуть код возврата ошибки. Вам нужно проверить этот код возврата, прежде чем продолжить:

flock <params> && <do other stuff>

so

( ( flock -x 200 ;  sleep 10 ; echo "original finished" ; ) 200>./test.lock ) & ( sleep 2 ; ( flock -x -w 2 200 && echo "a finished" ) 200>./test.lock ) &

делает то, что вы хотите.

person psmears    schedule 24.05.2010
comment
Что это за синтаксис, который позволяет вам делать 200›имя файла? 200 - это fd#? - person Dan; 28.01.2011
comment
@ user37078: Да, ›имя_файла означает перенаправление стандартного вывода (fd#1) на «имя файла»; 200›имя файла означает перенаправление fd#200 на «имя файла» - person psmears; 04.02.2011