19 Ağustos 2013 tarihinde, Randal L. Schwartz , Linux'ta, "[b] betiğinin yalnızca bir örneğinin yarış koşulları olmadan veya kilit dosyalarını temizlemek zorunda kalmadan" çalışmasını sağlamak için tasarlanan bu kabuk betiğini yayınladı :
#!/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
Reklamı yapıldığı gibi çalışıyor gibi görünüyor:
$ ./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
$
İşte anladığım şey:
- Komut dosyası (
<
) kendi içeriğinin bir kopyasını (yani buradan$0
)0
bir alt kabuğun STDIN'ine (yani dosya tanımlayıcısına ) yönlendirir. - Alt kabuk içinde, komut dosyası
flock -n -x
, dosya tanıtıcısında engelleyici olmayan, özel bir kilit ( ) almaya çalışır0
.- Bu deneme başarısız olursa, alt kabuk çıkar (ve yapacak başka bir şey olmadığından ana komut dosyası da gider).
- Deneme yerine başarılı olursa, alt kabuk istenen görevi çalıştırır.
İşte benim sorularım:
- Neden komut dosyasının, alt kabuk tarafından miras alınan bir dosya tanımlayıcısına, başka bir dosyanın içeriğinden ziyade kendi içeriğinin bir kopyasını yönlendirmesi gerekiyor ? (Farklı bir dosyadan yönlendirmeyi ve yeniden çalıştırmayı denedim ve yürütme sırası değişti: arka plan dışı görev arka plandan önce kilitlendi. Yani, belki de dosyanın içeriğini kullanmak yarış koşullarından kaçınır; ama nasıl?)
- Neden komut dosyasının, alt kabuk tarafından miras alınan bir dosya tanımlayıcısına, bir dosyanın içeriğinin bir kopyasını yine de yönlendirmesi gerekiyor?
- Dosya tanımlayıcıda özel bir kilidi
0
tek bir kabukta tutmak , aynı komut dosyasının farklı bir kabukta çalışan bir kopyasının dosya tanımlayıcıda özel bir kilitlenmesini neden önlüyor0
? Kabukları standart dosya tanımlayıcıları (kendi ayrı kopyalarını yok mu0
,1
ve2
, yani STDIN, STDOUT ve STDERR)?