как я понимаю если делать обычными rm, touch, то если нет гарантий на время выполнения то всегда race. В НетБСД есть shlock но он непортабельный. По моему очень важная потребность не удовлетворена.
Я делал так:
lock() { #Возвращает 1 если не удалось установить блокировку
local noclobber=`set -o | grep '^noclobber.*on$`
set -C
echo $$ >"$1" && return
test "$noclobber" && set +C
ps -o pid= -p `cat "$1"` && return 1
echo $$ >|"$1" #Тут все равно возможны проблемы.
return
}
Но я оптимист и редко запускаю конфликтующие программы одновременно:-)
Вот -- я такое сварганил. это конечно только для моих целей -- мне их нужно в пределах одного скрипта использовать но в котором форкаются подпроцессы.
# initializes lock $1 to state $2
boa_inilock()
{
rm -f ${BOA_PATH}${1}_lock_*
cat < /dev/null > ${BOA_PATH}${1}_lock_${2}
}
# echoes to stdout current state of lock $1
boa_getlock()
{
echo ${BOA_PATH}${1}_lock_* | xargs -n1 basename | head -n1 | sed "s/^${1}_lock_//"
}
# tries to set lock $1 to state $2 from state $3
# returns 0 on success, 1 on failure
boa_setlock()
{
lock_to=${BOA_PATH}${1}_lock_${2}
lock_from=${BOA_PATH}${1}_lock_${3}
if mv $lock_from $lock_to; then
return 0
fi
return 1
}
# tries to set lock $1 to state $2 from state $3
# it waits lock to appear in state $3 for $4 seconds, if lock appears in state $3 then lock is set to state $2 and it returns 0
# if this state has not appeared in elapse of $4 seconds then it returns 1
boa_setlock_wait()
{
if [ $4 -eq 0 ]; then
return boa_setlock $1 $2 $3
fi
STEP=10
WAIT=$(( $4 / $BOA_STEP + 1 ))
for (( i = 0; i < $WAIT; i++ )); do
sleep $STEP
if boa_setlock $1 $2 $3; then
return 0
fi
done
return 1
}