GNU/Linux >> Belajar Linux >  >> Linux

Mutex seluruh sistem dengan Python di Linux

Coba perpustakaan ilock:

from ilock import ILock

with ILock('Unique lock name'):
    # The code should be run as a system-wide single instance
    ...

Jawaban Unix "tradisional" adalah menggunakan kunci file. Anda dapat menggunakan lockf(3) untuk mengunci bagian file sehingga proses lain tidak dapat mengeditnya; penyalahgunaan yang sangat umum adalah menggunakan ini sebagai mutex antar proses. Setara dengan python adalah fcntl.lockf.

Biasanya Anda menulis PID dari proses penguncian ke dalam file kunci, sehingga kebuntuan karena proses mati saat menahan kunci dapat diidentifikasi dan diperbaiki.

Ini memberi Anda apa yang Anda inginkan, karena kunci Anda ada di ruang nama global (sistem file) dan dapat diakses oleh semua proses. Pendekatan ini juga memiliki keuntungan bahwa program non-Python dapat berpartisipasi dalam penguncian Anda. Sisi negatifnya adalah Anda memerlukan tempat untuk menyimpan file kunci ini; juga, beberapa sistem file tidak benar-benar mengunci dengan benar, jadi ada risiko bahwa ia akan gagal secara diam-diam untuk mencapai pengecualian. Anda memenangkan beberapa, Anda kehilangan beberapa.


Jawaban saya tumpang tindih dengan jawaban lain, tetapi hanya untuk menambahkan sesuatu yang dapat disalin-tempel orang, saya sering melakukan hal seperti ini.

class Locker:
    def __enter__ (self):
        self.fp = open("./lockfile.lck")
        fcntl.flock(self.fp.fileno(), fcntl.LOCK_EX)

    def __exit__ (self, _type, value, tb):
        fcntl.flock(self.fp.fileno(), fcntl.LOCK_UN)
        self.fp.close()

Dan kemudian gunakan sebagai:

print("waiting for lock")
with Locker():
    print("obtained lock")
    time.sleep(5.0)

Untuk menguji, lakukan touch lockfile.lck lalu jalankan kode di atas di dua atau lebih terminal berbeda (dari direktori yang sama).

PEMBARUAN:smwikipedia menyebutkan solusi saya khusus untuk unix. Saya membutuhkan versi portabel baru-baru ini dan muncul dengan yang berikut, dengan ide dari proyek github acak. Saya tidak yakin panggilan seek() diperlukan tetapi ada di sana karena Windows API mengunci posisi tertentu dalam file. Jika Anda tidak menggunakan file untuk apa pun selain penguncian, Anda mungkin dapat menghapus pencarian.

if os.name == "nt":
    import msvcrt

    def portable_lock(fp):
        fp.seek(0)
        msvcrt.locking(fp.fileno(), msvcrt.LK_LOCK, 1)

    def portable_unlock(fp):
        fp.seek(0)
        msvcrt.locking(fp.fileno(), msvcrt.LK_UNLCK, 1)
else:
    import fcntl

    def portable_lock(fp):
        fcntl.flock(fp.fileno(), fcntl.LOCK_EX)

    def portable_unlock(fp):
        fcntl.flock(fp.fileno(), fcntl.LOCK_UN)


class Locker:
    def __enter__(self):
        self.fp = open("./lockfile.lck")
        portable_lock(self.fp)

    def __exit__(self, _type, value, tb):
        portable_unlock(self.fp)
        self.fp.close()

Standar POSIX menentukan semafor antar-proses yang dapat digunakan untuk tujuan ini. http://linux.die.net/man/7/sem_overview

multiprocessing modul dalam Python dibangun di atas API ini dan lainnya. Secara khusus, multiprocessing.Lock menyediakan "mutex" lintas proses. http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

EDIT untuk menanggapi pertanyaan yang diedit:

Dalam bukti konsep Anda, setiap proses membuat Lock() . Jadi, Anda memiliki dua kunci terpisah. Itu sebabnya tidak ada proses yang menunggu. Anda harus berbagi kunci yang sama antar proses. Bagian yang saya tautkan di multiprocessing dokumentasi menjelaskan cara melakukannya.


Linux
  1. Cara menginstal Python di Linux Mint 20

  2. Instal Python di Rocky Linux 8

  3. Linux - Pemantauan Seluruh Sistem Panggilan Ke Fungsi Perpustakaan?

  1. Cara Menginstal Python 3.10 di Rocky Linux 8

  2. Cara menggunakan ekspor dengan Python di Linux

  3. Menginstal program Python di Linux

  1. Cara mengeksekusi file python di linux

  2. Perbarui python di linux 2.7 ke 3.5

  3. Apa itu spinlock di Linux?