`flock` время от времени дает сбой на настольном ПК, но не на ноутбуке. Возможно, проблема в неисправном оборудовании?

`flock` время от времени дает сбой на настольном ПК, но не на ноутбуке. Возможно, проблема в неисправном оборудовании?

Я использую приведенный ниже скрипт для стресс-теста монопольной блокировки с помощью flock.

На моем ноутбуке он всегда работает нормально.
Но когда я запускаю его на своем настольном ПК, он может случайно дать сбой, позволяя двум экземплярам работать одновременно (получая одну и ту же блокировку!).
Оба работают под управлением Ubuntu 20.04.

Итак, я подозреваю, что проблема связана с оборудованием моего компьютера. Может быть, с оперативной памятью?

Итак, мой вопрос, основываясь на совете, который дает мне Flock MissBehavior, как я могу отследить/определить, какая часть оборудования неисправна?
Я имею в виду, что Flock делает, чтобы указать, какое оборудование неисправно (или может быть низкого качества)?

Как я подтверждаю проблему:
я получаю все процессы flock, у которых есть дочерняя команда, совпадающая с полным именем скрипта пути (это то, что flock должен выполнить как дочернюю команду).
Кроме того, я регистрирую работу, выполненную каждым скриптом, и в этом журнале есть одновременная работа двух или более его экземпляров. Работа регистрируется только в случае получения блокировки.
Может быть, я неправильно настраиваю flock для предоставления исключительных/уникальных блокировок?
Я использую это на другом терминале сейчас тоже:
while true;do date;lslocks |grep flock;sleep 1;done

Сценарий: cat >flock.tst.sh;chmod +x flock.tst.sh

#!/bin/bash

LC_NUMERIC=en_US.UTF-8

# HELPERS:
#trash /tmp/flock.tst.log;for((i=0;i<20;i++));do flock.tst.sh&:;done #run this on shell
#pkill -fe flock.tst.sh #end all concurrent children trying to acquire the lock
#while true;do date;lslocks |grep flock;sleep 1;done #use this to check if there is more than one lock acquired, check also the log file to confirm it, and if there is two subsequent WORK on the terminal log, it means a problem happened too

: ${bDaemonizing:=false}
: ${bReport:=false} #help use this to show more log, but will be harder to read it.
: ${bCheck:=false} #help this will let the script check if there is more than one instance working, but it may be slow and make it more difficult to let the problem happen
if ! $bDaemonizing;then
  echo "this IS a daemon script, only one instace runnable"
  flSelf="`realpath $0`"
  
  #set -x 
  while ! bDaemonizing=true flock --timeout=$(bc <<< "0.2+0.0$RANDOM") "$flSelf" "$flSelf" "$@";do
    if $bCheck;then
      strParents="$(nice -n 19 pgrep -f "^flock --timeout=.* $flSelf $flSelf" |tr '\n' ',' |sed -r 's"(.*),"\1"')"
      if [[ -n "$strParents" ]];then
        anDaemonPid=( $(nice -n 19 pgrep --parent "$strParents" -f "$flSelf") )
        if((${#anDaemonPid[*]}>1));then echo "ERROR: more than one daemon, flock failed!? :(";ps --no-headers -o ppid,pid,cmd -p "${anDaemonPid[@]}";fi
        if $bReport && ((${#anDaemonPid[*]}==1));then echo "$$:Wait daemon stop running or 'kill ${anDaemonPid[0]}'";fi #could be: "already running, exiting.", but the new instance may have updated parameters that work as intended now.
      fi
    fi
  done
  
  exit #returns w/e flock does
fi

echo "$$:Work:`date`"
for((i=0;i<60;i++));do
  echo "`\
    echo $i;\
    date;\
    ps --no-headers -o ppid,pid,stat,state,pcpu,rss,cmd -p "$PPID";\
    ps --no-headers -o ppid,pid,stat,state,pcpu,rss,cmd -p "$$";\
  `" >>/tmp/flock.tst.log
  
  sleep 1
done
echo "$$:Done:`date`"


Некоторые результаты:
Как вы можете видеть, эксклюзивная блокировка была получена процессами 1458428(flock:1458427) и 1438949(flock:1438941) одновременно :(

Файл журнала (созданный скриптом) показывает эту проблему (на 50-й секунде произошел второй вход другого экземпляра, который не должен был получить блокировку):

2
Fri 22 Jan 17:03:16 -03 2021
1438953 1458427 S    S  0.0   784 flock --timeout=.22377 /home/myUser/bin/flock.tst.sh /home/myUser/bin/flock.tst.sh
1458427 1458428 S    S  0.0  3852 /bin/bash /home/myUser/bin/flock.tst.sh
50
Fri 22 Jan 17:03:16 -03 2021
1438925 1438941 S    S  0.0   788 flock --timeout=.229687 /home/myUser/bin/flock.tst.sh /home/myUser/bin/flock.tst.sh
1438941 1438949 S    S  0.0  3900 /bin/bash /home/myUser/bin/flock.tst.sh

lslockпоказывает это (while dateнаходится в скрипте как подсказка):

Fri 22 Jan 17:03:16 -03 2021
flock           1459088 FLOCK  1.8K WRITE* 0          0          0 /home/myUser/bin/flock.tst.sh
flock           1458427 FLOCK  1.8K WRITE  0          0          0 /home/myUser/bin/flock.tst.sh
flock           1438941 FLOCK  1.8K WRITE  0          0          0 /home/myUser/bin/flock.tst.sh (deleted)
Fri 22 Jan 17:03:17 -03 2021
flock           1459616 FLOCK  1.8K WRITE* 0          0          0 /home/myUser/bin/flock.tst.sh
flock           1458427 FLOCK  1.8K WRITE  0          0          0 /home/myUser/bin/flock.tst.sh
flock           1438941 FLOCK  1.8K WRITE  0          0          0 /home/myUser/bin/flock.tst.sh (deleted)

Журнал терминала (который породил множество одновременных экземпляров) показывает следующее:

1438949:Work:Fri 22 Jan 17:02:23 -03 2021
1458428:Work:Fri 22 Jan 17:03:14 -03 2021
1438949:Done:Fri 22 Jan 17:03:26 -03 2021
1476209:Work:Fri 22 Jan 17:04:02 -03 2021
1458428:Done:Fri 22 Jan 17:04:17 -03 2021

решение1

Гипотеза: как раз перед тем, как это произошло, вы сохранили скрипт. Ваш редактор сохранил копию, а затем переместил копию в исходный путь. Смотритекак Vim это делаетипочему.

В действительности старая блокировка все еще удерживалась на старом файле (inode). Это показано …/flock.tst.sh (deleted)в выводе lslocks. Но flockваш скрипт (еще один его экземпляр?) продолжал порождать использование пути. Когда путь начал указывать на другой inode, какому-то новому flockбыло разрешено получить новую блокировку. Это показано …/flock.tst.shв выводе lslocks.

Два замка были независимыми, они не могли блокировать друг друга, потому что они использовалидругойфайлы. Flock сработал как задумано.

На самом деле я могу воссоздать ваш результат, запустив два экземпляра скрипта (так, чтобы один получил блокировку, а другой продолжал попытки ее получить), а затем открыв его с помощью и сразу vimнаписав ( ). Альтернативный вариант::w

cp flock.tst.sh foo
mv foo flock.tst.sh

Связанный контент