Apa perintah Unix yang dapat digunakan sebagai semafor / kunci?

34

Saya ingin menjalankan beberapa skrip Bash shell secara paralel. Namun, saya ingin menghindari kondisi balapan. Apa perintah Unix yang benar - benar atom yang bisa saya gunakan untuk tujuan ini, dan bagaimana saya bisa menggunakannya?

Larry Wang
sumber
Apa yang Anda lakukan yang membutuhkan kerja paralel? Tidak bisakah Anda mengekspresikan dependensi dengan cara yang memungkinkan paralel make(1)untuk mengambil alih? (Yaitu, lakukan make -j 9jika Anda memiliki 8 core)? Ini memiliki keuntungan tambahan dari pekerjaan interleaving dengan granularity yang lebih halus.
vonbrand

Jawaban:

30

Jika lockfiletidak diinstal pada sistem Anda, maka mkdirakan melakukan pekerjaan: ini adalah operasi atom, dan gagal jika direktori sudah ada (selama Anda tidak menambahkan -psaklar baris perintah).

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"
}
Riccardo Murri
sumber
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

Ini memastikan bahwa kode antara "(" dan ")" dijalankan hanya oleh satu proses pada satu waktu dan bahwa proses menunggu kunci terlalu lama.

Alex B
sumber
Bagus, tidak tahu tentang itu. Namun, ini tampaknya khusus untuk Linux ...
Riccardo Murri
1
@Riccardo, FreeBSD memiliki perintah yang sama: lockf(1).
Alex B
lockf(1)tidak bekerja dengan cara yang digunakan dalam contoh ini. Tidak dapat menggunakan nomor deskriptor file sebagai argumen.
Charley
11

lockfile (1) terlihat seperti kandidat yang baik, namun berhati-hatilah bahwa itu adalah bagian dari paket procmail , yang mungkin belum Anda instal pada mesin Anda. Ini adalah paket yang cukup populer sehingga harus dikemas untuk sistem Anda jika belum diinstal. Tiga dari empat sistem yang saya periksa memilikinya, dan yang lainnya memilikinya.

Penggunaannya sederhana:

#!/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

Opsi yang saya berikan membuatnya coba lagi satu detik selama 15 detik. Jatuhkan bendera "-r" jika Anda ingin menunggu selamanya.

Warren Young
sumber
2
Hanya untuk referensi - halaman manual: linux.die.net/man/1/lockfile . :)
Lucas Jones
Ketahuilah bahwa (menurut halaman manual), "Setelah file terkunci, kunci harus disentuh setidaknya setiap lima menit atau kunci akan dianggap basi, dan upaya kunci berikutnya akan berhasil."
Jay
6

Panggilan sistem mkdir()bersifat atom pada sistem file POSIX. Jadi, menggunakan mkdirperintah sedemikian rupa sehingga hanya melibatkan satu panggilan untuk mkdir()mencapai tujuan Anda. (TKI, jangan gunakan mkdir -p). Buka kunci yang sesuai rmdirtentu saja.

Caveat emptor: mkdir()mungkin bukan atom pada sistem file jaringan.

Hari
sumber
Apakah rmdirkarena itu juga atom?
Alexej Magura
3

Mungkin perintah lockfile akan melakukan apa yang Anda butuhkan.

lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock
jacksonh
sumber
Ini sepertinya menghapus file yang salah.
Benjamin W.
1

Jika Anda hanya menjalankan Unix, gunakan fifos. Anda dapat menulis catatan kerja ke fifo dan meminta proses membaca dari file ini dan pembaca Anda akan memblokir fifos.

File kunci tidak masalah, tetapi untuk apa yang Anda jelaskan saya akan menggunakan fifos

Chris
sumber
1
Bisakah Anda menguraikan bagaimana menurut Anda fifos dapat mencegah kondisi balapan?
G-Man Mengatakan 'Reinstate Monica'