Я хочу запустити паралельно кілька сценаріїв оболонки Bash. Однак я хочу уникати перегонів. Які команди Unix є справді атомними, які я міг би використовувати для цієї мети, і як я можу їх використовувати?
Я хочу запустити паралельно кілька сценаріїв оболонки Bash. Однак я хочу уникати перегонів. Які команди Unix є справді атомними, які я міг би використовувати для цієї мети, і як я можу їх використовувати?
Відповіді:
Якщо lockfile
він не встановлений у вашій системі, тоді mkdir
буде виконуватися робота: це атомна операція, і вона виходить з ладу, якщо каталог вже існує (до тих пір, поки ви не додасте -p
комутатор командного рядка).
create_lock_or_wait () {
path="$1"
wait_time="${2:-10}"
while true; do
if mkdir "${path}.lock.d"; then
break;
fi
sleep $wait_time
done
}
remove_lock () {
path="$1"
rmdir "${path}.lock.d"
}
#!/bin/bash
# Makes sure we exit if flock fails.
set -e
(
# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10 200
# Do stuff
) 200>/var/lock/.myscript.exclusivelock
Це гарантує, що код між "(" і ")" запускається лише одним процесом за один раз і що процес чекає блокування занадто довго.
lockf(1)
.
lockf(1)
не працює так, як використовується в цьому прикладі. Він не може приймати номер дескриптора файлу як аргумент.
lockfile (1) виглядає як хороший кандидат, проте будьте уважні, що це частина пакета procmail , який ви, можливо, ще не встановили на своїй машині. Це досить популярний пакет, що його слід упакувати для вашої системи, якщо він ще не встановлений. У трьох із чотирьох систем, які я перевірив, вони є, а в іншій є.
Використовувати його просто:
#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`
echo Waiting for lock $LOCKFILE...
if lockfile -1 -r15 $LOCKFILE
then
# Do protected stuff here
echo Doing protected stuff...
# Then, afterward, clean up so another instance of this script can run
rm -f $LOCKFILE
else
echo "Failed to acquire lock! lockfile(1) returned $?"
exit 1
fi
Опції, які я дав, змушують його повторити раз на секунду до 15 секунд. Відкиньте прапор "-r", якщо ви хочете, щоб він чекав вічно.
У mkdir()
файлових системах POSIX системний виклик є атомним. Отже, використовуючи mkdir
команду таким чином, що вона передбачає рівно один дзвінок, щоб mkdir()
досягти вашої мети. (IOW, не використовувати mkdir -p
). Відповідне розблокування, rmdir
звичайно.
Caveat emptor: mkdir()
може бути не атомним у мережевих файлових системах.
rmdir
тому є також атомним?
Можливо, команда lockfile виконає все, що вам потрібно.
lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock
Якщо ви працюєте лише на Unix, використовуйте fifos. Ви можете писати робочі записи на файл fifo і мати з них прочитані процеси, і ваші читачі блокуються на файлі.
Файли блокування в порядку, але для того, що ви описуєте, я б пішов з фіфосом
Як зазначено тут: " Правильне блокування скриптів оболонки? ", За допомогою інструмента FLOM (Free LOck Manager) , серіалізація команд та скриптів оболонки стає так само просто, як і запуск
flom -- command_to_serialize
FLOM дозволяє реалізувати більш складні випадки використання (розподілене блокування, читачі / записи, числові ресурси тощо), як пояснено тут: http://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/
make(1)
перебирати? (тобто зробіть,make -j 9
якщо у вас є 8 ядер)? Це має додаткову перевагу переплетення роботи з тонкою деталізацією.