GNU/Linux >> Linux Esercitazione >  >> Linux

Qual è il modo migliore per garantire che sia in esecuzione solo un'istanza di uno script Bash?

Il blocco consultivo è stato utilizzato per secoli e può essere utilizzato negli script bash. Preferisco il semplice flock (da util-linux[-ng] ) su lockfile (da procmail ). E ricorda sempre una trappola all'uscita (sigspec ==EXIT o 0 , intercettare segnali specifici è superfluo) in quegli script.

Nel 2009 ho rilasciato il mio script lockable boilerplate (originariamente disponibile nella mia pagina wiki, oggi disponibile come Gist). Trasformarlo in un'istanza per utente è banale. Usandolo puoi anche scrivere facilmente script per altri scenari che richiedono un certo blocco o sincronizzazione.

Ecco il boilerplate menzionato per tua comodità.

#!/bin/bash
# SPDX-License-Identifier: MIT

## Copyright (C) 2009 Przemyslaw Pawelczyk <[email protected]>
##
## This script is licensed under the terms of the MIT license.
## https://opensource.org/licenses/MIT
#
# Lockable script boilerplate

### HEADER ###

LOCKFILE="/var/lock/`basename $0`"
LOCKFD=99

# PRIVATE
_lock()             { flock -$1 $LOCKFD; }
_no_more_locking()  { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking()  { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }

# ON START
_prepare_locking

# PUBLIC
exlock_now()        { _lock xn; }  # obtain an exclusive lock immediately or fail
exlock()            { _lock x; }   # obtain an exclusive lock
shlock()            { _lock s; }   # obtain a shared lock
unlock()            { _lock u; }   # drop a lock

### BEGIN OF SCRIPT ###

# Simplest example is avoiding running multiple instances of script.
exlock_now || exit 1

# Remember! Lock file is removed when one of the scripts exits and it is
#           the only script holding the lock or lock is not acquired at all.

Se lo script è lo stesso per tutti gli utenti, puoi utilizzare un lockfile approccio. Se acquisisci il blocco, procedi altrimenti mostra un messaggio ed esci.

Ad esempio:

[Terminal #1] $ lockfile -r 0 /tmp/the.lock
[Terminal #1] $ 

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] lockfile: Sorry, giving up on "/tmp/the.lock"

[Terminal #1] $ rm -f /tmp/the.lock
[Terminal #1] $ 

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] $ 

Dopo /tmp/the.lock è stato acquisito il tuo script sarà l'unico con accesso all'esecuzione. Quando hai finito, basta rimuovere il lucchetto. In forma di script potrebbe essere simile a:

#!/bin/bash

lockfile -r 0 /tmp/the.lock || exit 1

# Do stuff here

rm -f /tmp/the.lock

Penso flock è probabilmente la variante più semplice (e memorabile). Lo uso in un cron job per codificare automaticamente dvd e cd

# try to run a command, but fail immediately if it's already running
flock -n /var/lock/myjob.lock   my_bash_command

Usa -w per i timeout o le opzioni di tralasciare attendere fino a quando il blocco non viene rilasciato. Infine, la pagina man mostra un bell'esempio per più comandi:

   (
     flock -n 9 || exit 1
     # ... commands executed under lock ...
   ) 9>/var/lock/mylockfile

Linux
  1. Qual è l'uso di $# in Bash

  2. Limita un programma gui in Linux a una sola istanza

  3. È possibile recuperare il contenuto di uno script bash in esecuzione dalla RAM

  4. Qual è il modo migliore per verificare se un volume è montato in uno script Bash?

  5. Qual è il modo migliore per ottenere informazioni sulle unità attualmente non montate?

Qual è la differenza tra l'esecuzione di uno script Bash e l'approvvigionamento?

Ho appena cancellato /bin. Qual è il modo migliore per recuperare?

Qual è il modo migliore per unire nuovamente i file dopo averli divisi?

Qual è il modo migliore per imparare SELinux?

Qual è il modo più veloce per eseguire uno script?

Qual è il modo migliore per impostare una variabile d'ambiente in .bashrc?