Domanda

Ho un lungo processo e ne ho bisogno per avviare un altro processo (che funzionerà anche per un bel po '). Devo solo avviarlo e poi dimenticarmene completamente.

Sono riuscito a fare ciò di cui avevo bisogno raccogliendo un po 'di codice dal libro Ruby di programmazione, ma mi piacerebbe trovare il modo migliore / giusto e capire cosa sta succedendo. Ecco cosa ho ottenuto inizialmente:

exec("whatever --take-very-long") if fork.nil?
Process.detach($)

Quindi, è così o in quale altro modo dovrei farlo?

Dopo aver verificato le risposte sotto ho finito con questo codice, che sembra avere più senso:

(pid = fork) ? Process.detach(pid) : exec("foo")

Gradirei qualche spiegazione su come funziona fork . [capito già]

Il distacco di $$ era corretto? Non so perché funzioni, e mi piacerebbe davvero avere una migliore comprensione della situazione.

È stato utile?

Soluzione

La funzione fork separa il processo in due.

I processi

?? Entrambi ricevono quindi il risultato della funzione. Il bambino riceve un valore pari a zero / nil (e quindi sa che è il figlio) e il genitore riceve il PID del figlio.

Quindi:

exec("something") if fork.nil?

farà iniziare il processo figlio " qualcosa " e il processo genitore proseguirà dove si trovava.

Nota che exec () sostituisce l'attuale processo con " qualcosa " ;, quindi il processo figlio non eseguirà mai nessun codice Ruby successivo.

La chiamata a Process.detach () sembra che potrebbe essere errata. Mi sarei aspettato che contenesse il PID del bambino, ma se leggo bene il tuo codice si sta effettivamente staccando il processo genitore.

Altri suggerimenti

Alnitak ha ragione. Ecco un modo più esplicito per scriverlo, senza $$

pid = Process.fork
if pid.nil? then
  # In child
  exec "whatever --take-very-long"
else
  # In parent
  Process.detach(pid)
end

Lo scopo del distacco è solo quello di dire, "non mi interessa quando il bambino termina" per evitare processi di zombi .

Rimuovere $$ non era corretto. Da p. 348 del piccone (2a edizione):

  

$$ Fixnum Il numero di processo del programma in esecuzione. [r / o]

Questa sezione, " Variabili e costanti " nella " Ruby Language " capitolo, è molto utile per decodificare varie costanti $ di rubini - tuttavia l'edizione online (la prima

Quindi quello che stavi effettivamente facendo era staccare il programma da se stesso, non dal suo bambino. Come altri hanno già detto, il modo corretto di staccarsi dal bambino è usare il pid del bambino restituito da fork () .

Le altre risposte sono buone se sei sicuro di voler staccare il processo figlio. Tuttavia, se non ti dispiace o preferisci mantenere collegato il processo figlio (ad esempio stai lanciando sottoserver / servizi per un'app Web), puoi sfruttare la seguente scorciatoia

fork do
    exec('whatever --option-flag')
end

Fornire un blocco dice a fork di eseguire quel blocco (e solo quel blocco) nel processo figlio, continuando nel padre.

Ho trovato le risposte sopra rotto il mio terminale e incasinato l'output. questa è la soluzione che ho trovato.

   system("nohup ./test.sh &")

nel caso in cui qualcuno abbia lo stesso problema, il mio obiettivo era quello di accedere a un server SSH e quindi mantenere quel processo in esecuzione a tempo indeterminato. quindi test.sh è questo

#!/usr/bin/expect -f
spawn ssh host -l admin -i cloudkey  
expect "pass"
send "superpass\r"
sleep 1000000
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top