2015-02-18 3 views
2
#!/bin/bash 
if [ ! -f numbers ]; then echo 0 > numbers; fi 
count=0 
touch numbers 
echo $count > numbers 
while [[ $count != 100 ]]; do 
    if ln numbers numbers.lock 
    then 
    count=`expr $count + 1` 
    n=`tail -1 numbers` 
    expr $n + 1 >> numbers 
    rm numbers.lock 
    fi 
done 

Что я могу сделать, чтобы избежать состояния гонки в count=`expr $count + 1` и n=`tail -1 numbers`, так что, когда я бегу двух сценариев в то же время, он идет только до 100, а не 200. Я исследовал на нескольких сайтов, но нет кратких ответов без огромной функции.Как избежать условий гонки в сценарии bash?

+0

Почему вы запускаете этот сценарий дважды в одно и то же время? Почему вы не используете безопасный временный файл для своего хранилища? –

+0

использовать 'flock' из' util-linux' –

+0

@EtanReisner его а так мы узнаем, что есть условия гонки, и их нужно избегать – StingRay21

ответ

3

Вы уже безопасно избегаете фактического состояния гонки с помощью файла блокировки. Проблему, которую вы описываете, можно избежать двумя способами.

(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 должен управляться файлом блокировки.

+0

спать 1, а не спать 1 правильно? – StingRay21

+0

Исправить (-: и исправлено сейчас – tripleee

+0

Спасибо, сэр :)! – StingRay21

Смежные вопросы