Il 19 agosto 2013, Randal L. Schwartz ha pubblicato questo script di shell, che aveva lo scopo di garantire, su Linux, "che sia in esecuzione solo un'istanza di [lo] script, senza condizioni di competizione o che debba ripulire i file di blocco":
#!/bin/sh
# randal_l_schwartz_001.sh
(
if ! flock -n -x 0
then
echo "$$ cannot get flock"
exit 0
fi
echo "$$ start"
sleep 10 # for testing. put the real task here
echo "$$ end"
) < $0
Sembra funzionare come pubblicizzato:
$ ./randal_l_schwartz_001.sh & ./randal_l_schwartz_001.sh
[1] 11863
11863 start
11864 cannot get flock
$ 11863 end
[1]+ Done ./randal_l_schwartz_001.sh
$
Ecco cosa capisco:
- Lo script reindirizza (
<
) una copia del proprio contenuto (ovvero da$0
) allo STDIN (ovvero descrittore di file0
) di una subshell. - All'interno della subshell, lo script tenta di ottenere un blocco esclusivo (
flock -n -x
) non bloccante sul descrittore di file0
.- Se quel tentativo fallisce, la subshell esce (e così fa lo script principale, poiché non c'è nient'altro da fare).
- Se invece il tentativo ha esito positivo, la subshell esegue l'attività desiderata.
Ecco le mie domande:
- Perché lo script deve reindirizzare, a un descrittore di file ereditato dalla subshell, una copia del proprio contenuto anziché, diciamo, il contenuto di qualche altro file? (Ho provato a reindirizzare da un file diverso e rieseguire come sopra, e l'ordine di esecuzione è cambiato: l'attività non in background ha ottenuto il blocco prima di quello in background. Quindi, forse usando i contenuti del file si evitano le condizioni di gara; ma come?)
- Perché lo script deve reindirizzare, a un descrittore di file ereditato dalla subshell, una copia del contenuto di un file, comunque?
- Perché tenere un blocco esclusivo sul descrittore di file
0
in una shell impedisce a una copia dello stesso script, eseguita in una shell diversa, di ottenere un blocco esclusivo sul descrittore di file0
? Non conchiglie hanno le proprie, copie separate dei descrittori di file standard (0
,1
, e2
, cioè STDIN, stdout e stderr)?