2010-09-14 23 views

risposta

20

Il modo più comune è quello di creare un file PID: definire una posizione in cui il file andrà (dentro/var/run è comune). In caso di avvio riuscito, scriverai il tuo PID in questo file. Al momento di decidere se avviarsi, leggere il file e verificare che il processo di riferimento non esista (o se lo fa, che non è un'istanza del demone: su Linux, è possibile consultare /proc/$PID/exe). All'arresto, è possibile rimuovere il file ma non è strettamente necessario.

Ci sono degli script per aiutarti a fare questo, potresti trovare utile start-stop-daemon: può usare i file PID o anche solo verificare globalmente l'esistenza di un eseguibile. È stato progettato proprio per questo compito ed è stato scritto per aiutare le persone a farlo bene.

+0

In genere è una buona idea usare 'flock' su un file pid per assicurarsi che il processo che usa il pid sia, di fatto, il tuo. – Hasturkun

+0

Sì, metti un blocco esclusivo sul file pid e lascialo lì. Se il blocco fallisce, è in esecuzione un'altra istanza. – MarkR

+0

Dipende dal fatto che si stia scrivendo il file PID utilizzando il processo daemon o meno: se si utilizza 'start-stop-daemon' o simile, non è possibile bloccare il file in questo modo. Inoltre, anche se riesci a ottenere il blocco, dovresti comunque controllare il PID contenuto nel file, quindi non sono sicuro che ti guadagni molto. –

3

Se si ha accesso al codice (cioè sono scriverlo):

  • creare un file temporaneo, bloccarlo, rimuovere una volta fatto, return 1; se file esiste, o,
  • processi lista, return 1; se il nome del processo è nella lista

Se non lo fai:

  • creat e un wrapper di avvio per il programma che fa uno dei precedenti
+0

Ok , sembra interessante. Ma cosa succede se il processo viene ucciso prima che possa rimuovere il file temporaneo? –

+0

Questo è un problema, si. Potresti usare il secondo metodo per evitare questo problema, comunque. –

+0

Oppure un normale file come 'application.pid' su cui ottenere un blocco esclusivo, che alla fine dell'applicazione sarebbe stato rilasciato. – mhitza

2

Non so quale sia il vostro esatto requisito ma ho avuto un requisito simile; in quel caso ho avviato il mio demone da uno script Shell (era una macchina HP-UX) e prima di avviare il demone ho controllato se un exec con lo stesso nome è già in esecuzione. Se è; quindi non iniziare uno nuovo.

In questo modo sono stato anche in grado di controllare il numero di istanze di un processo.

+0

e come si controlla se "un exec con lo stesso nome è già in esecuzione"? – phunehehe

+0

È possibile elencare i processi in esecuzione utilizzando il comando 'ps'. Almeno in HP-UX. – Vaibhav

+0

Ho uno script che funziona così. È molto utile, ma è impossibile farlo in modo affidabile. Per esempio. se exec è uno script, quello che vedrai in esecuzione è l'interprete (sh, o perl o qualsiasi altra cosa) e il nome dello script è il primo argomento. Ma è anche possibile eseguire un programma con un nome falso, nel qual caso non si sa come identificarlo. Puoi anche guardare il filesystem/proc. Ma non c'è modo di renderlo affidabile al 100%. – reinierpost

5

Utilizzare boost interprocess library per creare un blocco di memoria che verrà creato dal processo. Se esiste già, significa che c'è un'altra istanza del processo. Uscita.

Il collegamento più preciso a quello che ti serve è this one.

#include <boost/interprocess/shared_memory_object.hpp> 
#include <boost/scoped_ptr.hpp> 

int main() 
{ 
    using boost::interprocess; 
    boost::scoped_ptr<shared_memory_object> createSharedMemoryOrDie; 
    try 
    { 
    createSharedMemoryOrDie.reset( 
     new shared_memory_object(create_only, "shared_memory", read_write)); 
    } catch(...) 
    { 
    // executable is already running 
    return 1; 
    } 

    // do your thing here 
} 
+1

Funzionerà se il processo viene ucciso con -9 prima che possa liberare shared_memory_object? – rustyx

2

penso che questo schema dovrebbe funzionare (ed è anche resistente agli urti):
Presupposto: C'è un file PID per l'applicazione (in genere in/var/run /)
1. Tentare di aprire il file PID
2. Se non esiste, crearlo e scrivere il PID su di esso. Continuare con il resto del programma
3. Se esiste, leggere il PID
4. Se il PID è ancora in esecuzione e è un'istanza del programma, quindi uscire
5. Se il PID non esiste o viene utilizzato da un altro programma, rimuovere il file PID e andare al passaggio 2.
6. Al termine del programma, rimuovere il file PID.

Il ciclo del passaggio 5 garantisce che, se due istanze vengono avviate contemporaneamente, solo una verrà eseguita alla fine.

+0

Non rimuoverei il file pid se non ha il tuo pid in quanto può introdurre una condizione di competizione. – MarkR

0

Avere un file pid e all'avvio fare un 'kill -0 <pid>'. Dove è il valore letto dal file. Se la risposta è! = 0, il daemon non è vivo e potresti riavviarlo.

Un altro approccio sarebbe quello di collegarsi a una porta e gestire l'eccezione di bind al secondo tentativo di avviare il demone. Se la porta è in uso, esci altrimenti continua a eseguire il demone.

+2

Il kill -0 ti dirà solo che il processo esiste, non che è il tuo demone. Ho visto un fastidioso bug dove (al momento dell'avvio, dove i numeri pid sono sequenziali) un altro processo prende lo stesso pid e ha causato un errore erroneo all'avvio di un daemon. – MarkR

-1

Credo che la mia soluzione è la più semplice:

(non usarlo se la condizione di corsa è uno scenario possibile, ma in tutti gli altri casi si tratta di una soluzione semplice e soddisfacente)

#include <sys/types.h> 
#include <unistd.h> 
#include <sstream> 

void main() 
{ 
    // get this process pid 
    pid_t pid = getpid(); 

    // compose a bash command that: 
    // check if another process with the same name as yours 
    // but with different pid is running 
    std::stringstream command; 
    command << "ps -eo pid,comm | grep <process name> | grep -v " << pid; 
    int isRuning = system(command.str().c_str()); 
    if (isRuning == 0) { 
     cout << "Another process already running. exiting." << endl; 
     return 1; 
    } 
    return 0; 
} 
Problemi correlati