Gerçek kullanım için, en çok oylanan cevabı kullanmalısınız .
Bununla birlikte, ps
insanların kullandıklarını görmeye devam ettiğim için kullanmaya başladığım çeşitli kırık ve yarı uygulanabilir yaklaşımları ve sahip oldukları birçok uyarıyı tartışmak istiyorum .
Bu cevap gerçekten "Neden kullanmıyor ps
ve grep
kabuktaki kilitlemeyi kullanmıyorsun ?"
Kırık yaklaşım # 1
İlk olarak, bir başka cevapta verilen ve çalışmadığı (ve asla çalışamadığı) ve açıkça hiç test edilmediği gerçeğine rağmen birkaç öneme sahip olan bir yaklaşım :
running_proc=$(ps -C bash -o pid=,cmd= | grep my_script);
if [[ "$running_proc" != "$$ bash my_script" ]]; do
echo Already locked
exit 6
fi
Sözdizimi hatalarını ve bozuk ps
argümanları düzeltelim ve alalım :
running_proc=$(ps -C bash -o pid,cmd | grep "$0");
echo "$running_proc"
if [[ "$running_proc" != "$$ bash $0" ]]; then
echo Already locked
exit 6
fi
Bu komut dosyası olacak hep olursa olsun çalıştırmak nasıl, 6, her seferinde çıkın.
Eğer onu çalıştırırsanız ./myscript
, o zaman ps
çıktı sadece 12345 -bash
gerekli dizge ile eşleşmeyecek 12345 bash ./myscript
, böylece başarısız olacaktır.
Eğer onu çalıştırırsan bash myscript
, işler daha da ilginçleşir. Bash işlemi çatal boru hattını çalıştırmak için ve çocuk kabuk çalıştırır ps
ve grep
. Hem orijinal kabuk hem de alt kabuk ps
çıktıda görünecek , şöyle:
25793 bash myscript
25795 bash myscript
Beklenen çıktı $$ bash $0
bu değil, bu yüzden komut dosyanızdan çıkılacak.
Kırık yaklaşım # 2
Şimdi # 1 numaralı yaklaşımı yazan kullanıcıya bütün adalet içinde, bunu ilk denediğimde kendime benzer bir şey yaptım:
if otherpids="$(pgrep -f "$0" | grep -vFx "$$")" ; then
echo >&2 "There are other copies of the script running; exiting."
ps >&2 -fq "${otherpids//$'\n'/ }" # -q takes about a tenth the time as -p
exit 1
fi
Bu neredeyse işe yarıyor. Ancak boruyu çalıştırmak için çatallanma gerçeği bunu atar. Yani bu da daima çıkacak.
Güvenilmez yaklaşım # 3
pids_this_script="$(pgrep -f "$0")"
if not_this_process="$(echo "$pids_this_script" | grep -vFx "$$")"; then
echo >&2 "There are other copies of this script running; exiting."
ps -fq "${not_this_process//$'\n'/ }"
exit 1
fi
Bu sürüm, ilk önce # 2'de mevcut komut dosyasını kendi komut satırı argümanlarında bulunan tüm PID'leri almak ve ardından mevcut komut dosyasının PID'sini atlamak için ayrı ayrı filtrelemek suretiyle boru hattı oluşturma sorununu önler .
Bu işe yarayabilir ... başka hiçbir işlem ile eşleşen bir komut satırı bulunmazsa $0
ve komut dosyasının her zaman aynı şekilde çağrılması sağlanır (örneğin, göreceli bir yolla ve sonra mutlak bir yolla çağrılırsa, ikinci örnek önceki ile aynı olmaz) ).
Güvenilmez yaklaşım # 4
Peki ya tam komut satırını kontrol etmeyi atlarsak, bu gerçekten çalışan bir betiği göstermeyebilir ve lsof
bunun yerine bu betiği açık olan tüm işlemleri bulmak için kontrol edebilirsek ne olur ?
Evet, bu yaklaşım aslında çok da kötü değil:
if otherpids="$(lsof -t "$0" | grep -vFx "$$")"; then
echo >&2 "Error: There are other processes that have this script open - most likely other copies of the script running. Exiting to avoid conflicts."
ps >&2 -fq "${otherpids//$'\n'/ }"
exit 1
fi
Tabii ki, betiğin bir kopyası çalışıyorsa, o zaman yeni örnek çalışmaya başlar ve iki kopya çalışır.
Veya çalışan komut dosyası değiştirilirse (örneğin Vim veya a ile git checkout
), komut dosyasının "yeni" sürümü sorun çıkarmayacaktır, çünkü hem Vim hem de yerine git checkout
yeni bir dosya (yeni bir inode) çıkar. eski olan.
Ancak, komut dosyası asla değiştirilmez ve hiçbir zaman kopyalanmazsa, bu sürüm oldukça iyidir. Yarış koşulu yoktur, çünkü komut dosyasına kontrole ulaşılmadan önce açık olması gerekir.
Komut dosyası açık olan başka bir işlem açık olsa da yanlış pozitif olabilir, ancak Vim'de düzenleme için açık olsa bile, vim komut dosyasını açık tutmuyor, bu yüzden yanlış pozitif sonuçlanmayacak.
Ancak unutmayın, eğer senaryo düzenlenmiş veya kopyalanmışsa, yanlış negatifler ( yani aynı anda çalışan birden fazla örnek) alacağınız için bu yaklaşımı kullanmayın - Vim ile düzenlemenin yanlış pozitifler vermemesi önemli değil. sana. Yaklaşım 3. çünkü, ama, bundan söz etmez Vim ile açık senaryoyu varsa (yani başlangıç reddediyor) yanlış pozitif vermek.
Öyleyse ne yapmalı?
Bu soruya en çok oylanan cevap iyi bir yaklaşım getiriyor.
Belki daha iyi bir tane yazabilirsiniz ... ama tüm problemleri anlamadıysanız ve yukarıdaki tüm yaklaşımlarla uyarırsanız, hepsini önleyen bir kilitleme yöntemi yazmanız mümkün değildir.
kill
; ve sadece bir dokunuşundan ziyade, bir kişinin kendi yardımını kilit dosyaya koymak iyi bir uygulama gibi görünüyor.