Ich verwende das folgende Skript, um den exklusiven Sperrvorgang mit einem Stresstest zu unterziehen flock
.
Auf meinem Notebook funktioniert es immer einwandfrei.
Aber wenn ich es auf meinem Desktop-PC ausführe, kann es zufällig fehlschlagen, sodass zwei Instanzen gleichzeitig ausgeführt werden (und dieselbe Sperre erhalten!).
Beide laufen unter Ubuntu 20.04.
Ich vermute also ein Hardwareproblem auf meinem Desktop. Liegt es vielleicht am RAM?
Meine Frage ist also: Wie kann ich anhand des Hinweises, den Flock Missbehavior mir gibt, nachverfolgen/bestimmen, welches Hardwareteil defekt ist?
Ich meine, welcher Flock könnte darauf hinweisen, welche Hardware defekt ist (oder möglicherweise von schlechter Qualität ist)?
So bestätige ich das Problem:
Ich erhalte alle Flock-Prozesse, deren untergeordnete Befehle mit dem vollständigen Pfad des Skriptnamens übereinstimmen (das ist das, was Flock als untergeordneten Befehl ausführen sollte).
Außerdem protokolliere ich die von jedem Skript ausgeführte Arbeit und in diesem Protokoll ist die gleichzeitige Arbeit von zwei oder mehr seiner Instanzen aufgeführt. Die Arbeit wird nur protokolliert, wenn die Sperre erworben wurde.
Könnte es sein, dass ich Flock nicht richtig konfiguriert habe, um exklusive/eindeutige Sperren bereitzustellen?
Ich verwende dies jetzt auch auf einem anderen Terminal:
while true;do date;lslocks |grep flock;sleep 1;done
Das Skript:
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`"
Einige Ergebnisse:
Wie Sie sehen können, wurde die exklusive Sperre gleichzeitig von den Prozessen 1458428(flock:1458427) und 1438949(flock:1438941) erworben :(
Die (vom Skript erstellte) Protokolldatei zeigt dieses Problem (bei Sekunde 50 trat ein Protokoll der zweiten Sekunde der anderen Instanz auf, die die Sperre nicht hätte erhalten sollen):
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
zeigt dies (das while-Symbol date
steht im Skript als Hinweis):
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)
Das Terminalprotokoll (das die vielen gleichzeitigen Instanzen hervorgebracht hat) zeigt Folgendes:
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
Antwort1
Hypothese: Kurz bevor es passierte, haben Sie das Skript gespeichert. Ihr Editor hat eine Kopie davon gespeichert und diese dann an den ursprünglichen Pfad verschoben. Siehewie Vim das machtUndWarum.
Tatsächlich wurde die alte Sperre immer noch auf der alten Datei (Inode) gehalten. Dies zeigte sich wie …/flock.tst.sh (deleted)
in der Ausgabe von lslocks
. Aber flock
Ihr Skript (eine andere Instanz davon?) erzeugte weiterhin den Pfad „use the path“. Als der Pfad anfing, auf einen anderen Inode zu zeigen, flock
durfte ein neuer eine neue Sperre erwerben. Dies zeigte sich wie …/flock.tst.sh
in der Ausgabe von lslocks
.
Die beiden Schlösser waren unabhängig voneinander, sie konnten sich nicht gegenseitig blockieren, da sieandersDateien. Flock funktionierte wie vorgesehen.
Ich kann Ihr Ergebnis tatsächlich reproduzieren, indem ich zwei Instanzen des Skripts ausführe (eine erhält die Sperre und eine andere versucht weiter, sie zu erhalten) und es dann mit öffne und sofort vim
( ) schreibe . Alternativ::w
cp flock.tst.sh foo
mv foo flock.tst.sh