Вы уже безопасно избегаете фактического состояния гонки с помощью файла блокировки. Проблему, которую вы описываете, можно избежать двумя способами.
(1) Переместите файл блокировки вне основного цикла, чтобы два экземпляра вашей программы не могли одновременно запускать свой основной цикл. Если кто-то запускается, другой должен будет подождать, пока это будет сделано, а затем начните замену выходного файла.
#!/bin/bash
while true; do
if ! ln numbers numbers.lock
then
sleep 1
else
if [ ! -f numbers ]; then echo 0 > numbers; fi
count=0
touch numbers
#echo $count > numbers # needless, isn't it?
while [[ $count != 100 ]]; do
count=`expr $count + 1`
n=`tail -1 numbers`
expr $n + 1 >> numbers
rm numbers.lock
done
break
fi
done
(2) Сделайте два экземпляра сотрудничающими, изучив, что представляет собой содержимое файла. Другими словами, заставить их прекратить цикл, когда число достигает 100, независимо от того, сколько других процессов записывает этот файл. (Я предполагаю, что это ненадежный углом случай, когда есть более 100 экземпляров подряд.)
#!/bin/bash
# FIXME: should properly lock here, too
if [ ! -f numbers ]; then echo 0 > numbers; fi
n=0
touch numbers
while [[ $n -lt 100 ]]; do
if ln numbers numbers.lock
then
n=$(expr $(tail -1 numbers) + 1 | tee numbers)
rm numbers.lock
fi
done
В зависимости от ваших потребностей, вы можете на самом деле хотите, чтобы сценарий затирать любые предыдущие значения в файле, когда создается новый экземпляр скрипт запускается, но если нет, то echo 0 > numbers
должен управляться файлом блокировки.
Почему вы запускаете этот сценарий дважды в одно и то же время? Почему вы не используете безопасный временный файл для своего хранилища? –
использовать 'flock' из' util-linux' –
@EtanReisner его а так мы узнаем, что есть условия гонки, и их нужно избегать – StingRay21