
Я хочу запустить несколько скриптов оболочки Bash параллельно. Однако я хочу избежать состояния гонки. Какие команды Unixдействительноатомарные, которые я мог бы использовать для этой цели, и как их можно использовать?
решение1
#!/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
Это гарантирует, что код между «(» и «)» будет выполняться только одним процессом одновременно, и что процесс не будет слишком долго ожидать блокировки.
решение2
Если 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"
}
решение3
lockfile(1) выглядит как хороший кандидат, хотя имейте в виду, что он является частьюпрокмейлпакет, который вы, возможно, еще не установили на своей машине. Это достаточно популярный пакет, который должен быть упакован для вашей системы, если он еще не установлен. В трех из четырех систем, которые я проверил, он есть, а в другой он доступен.
Использовать его просто:
#!/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", если хотите, чтобы он ждал вечно.
решение4
Возможно, команда lockfile сделает то, что вам нужно.
lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock