Hangi Unix komutları semafor / kilit olarak kullanılabilir?


34

Paralel olarak birden fazla Bash kabuk betiği çalıştırmak istiyorum. Ancak yarış koşullarından kaçınmak istiyorum. Hangi Unix komutları bu amaçla kullanabileceğim gerçekten atomiktir ve bunları nasıl kullanabilirim?


Paralel çalışma gerektiren ne yapıyorsunuz? Bağımlılıkları bir paralelin make(1)ele geçirilmesine izin verecek şekilde ifade edemez misiniz ? (yani, make -j 98 çekirdeğiniz varsa bir yapalım )? Bu, daha ince ayrıntı dereceli birleştirme çalışmasının ilave avantajına sahiptir.
vonbrand

Yanıtlar:


30

Eğer lockfilesisteminizde yüklü değilse, o zaman mkdirbunun bir atom işlemdir ve dizin zaten (sürece katmayan olarak var eğer başarısız: iş yapacak -pkomut satırı anahtarı).

create_lock_or_wait () {
  path="$1"
  wait_time="${2:-10}"
  while true; do
        if mkdir "${path}.lock.d"; then
           break;
        fi
        sleep $wait_time
  done
}

remove_lock () {
  path="$1"
  rmdir "${path}.lock.d"
}

26

flock(1)

#!/bin/bash

# Makes sure we exit if flock fails.
set -e

(
  # Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
  flock -x -w 10 200

  # Do stuff

) 200>/var/lock/.myscript.exclusivelock

Bu, "(" ve ")" arasındaki kodun aynı anda yalnızca bir işlem tarafından çalıştırılmasını ve işlemin çok uzun süre kilitlenmesini beklemesini sağlar.


Güzel olan, bilmiyordum. Ancak, görünüşe göre Linux özgü ...
Riccardo Murri

1
@Riccardo, FreeBSD benzer komutu vardır: lockf(1).
Alex B

lockf(1)Yine de, bu örnekte kullanılan şekilde çalışmaz. Bir dosya tanıtıcı numarasını argüman olarak kabul edemez.
Charley,

11

lockfile (1) , makinenize henüz yüklememiş olabileceğiniz procmail paketinin bir parçası olmasına rağmen, iyi bir aday gibi görünüyor . Henüz kurulmamışsa, sisteminiz için paketlenmesi gereken yeterince popüler bir pakettir. Kontrol ettiğim dört sistemden üçünde buna, diğerinde mevcut.

Kullanımı basittir:

#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`

echo Waiting for lock $LOCKFILE...
if lockfile -1 -r15 $LOCKFILE
then
    # Do protected stuff here
    echo Doing protected stuff...

    # Then, afterward, clean up so another instance of this script can run
    rm -f $LOCKFILE
else
    echo "Failed to acquire lock!  lockfile(1) returned $?"
    exit 1
fi

Verdiğim seçenekler saniyede bir kez 15 saniyeye kadar tekrar denemesini sağlar. Sonsuza dek beklemesini istiyorsanız, "-r" bayrağını bırakın.


2
Sadece referans için - kılavuz sayfası: linux.die.net/man/1/lockfile . :)
Lucas Jones,

(Manpage'e göre), "Bir dosya kilitlendiğinde, her beş dakikada bir kez kilit dokunulmalıdır, aksi takdirde kilit bayatlanmış sayılır ve sonraki kilitleme girişimlerinin başarılı olacağını" unutmayın.
Jay

6

Sistem çağrısı mkdir()POSIX dosya sistemlerinde atomiktir. Bu nedenle, mkdirkomutu mkdir(), amacınıza ulaşmak için tek bir çağrıyı içerecek şekilde kullanmak. (IOW, kullanmayın mkdir -p). Karşılık gelen kilit açma rmdirelbette.

Uyarıcı emptor: mkdir()ağ dosya sistemlerinde atomik olmayabilir.


bu rmdirnedenle de atomik mi?
Alexej Magura

3

Belki de lockfile komutu ihtiyacınız olanı yapar.

lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock

Bu yanlış dosyayı silmek gibi görünüyor.
Benjamin W.,

1

Sadece Unix ile çalışıyorsanız, fifos kullanın. Çalışma kayıtlarını fifoya yazabilir ve bu dosyadan işlemlerin okunmasını sağlayabilirsiniz; okuyucularınız beşlikte engelleyecektir.

Kilit dosyaları iyi, ancak tanımladığınız şey için fifos ile giderim


1
Fiveo'ların yarış koşullarını nasıl önleyebileceğini düşündüğünüzü açıklayabilir misiniz?
G-Man

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.