Come posso rinnegare un processo in esecuzione e associarlo a una nuova shell dello schermo?


159

Ho un programma in esecuzione su una shell SSH. Voglio metterlo in pausa ed essere in grado di interrompere la sua esecuzione quando torno.

Un modo in cui pensavo di farlo era trasferire la sua proprietà su una shell dello schermo, facendola funzionare lì.

C'è un modo diverso di procedere?


8
Vedi anche Posso nohup / screen un processo già avviato? e riprendi il comando in esecuzione nella sessione SSH rilasciata , che menzionano diverse soluzioni basate su ptrace non (attualmente) menzionate qui.
Gilles,

Da domande come unix.stackexchange.com/a/4039/13496 ho sentito parlare di retty e neercs . Hmmm ... mi chiedo se c'è qualcosa di simile a uno strato di " schermo qui" prima di eseguire un processo la prossima volta se dovessi perdere il terminale superiore in futuro, ciò renderà più semplice tornare indietro nello stdin / out / err
Marcos

Il problema secondario / implicito in questa domanda che non riesco a capire è ... perché la shell ha scelto di rinnegare un lavoro sospeso quando ce n'è uno più recente / appena avviato in background che non ha nemmeno bisogno / attesa di stdin? Questo è il trattamento al quale mi sono abituato, quindi non so cosa sia cambiato qui ...
Marcos,

Risposte:


86

Usare GNU screenè la soluzione migliore.

Avvia schermata in esecuzione al primo accesso: eseguo screen -D -R, eseguo il comando e disconnetto o lo sospendo con CTRL-Ze quindi disconnetto dallo schermo premendo CTRL-Aquindi D.

Quando si accede nuovamente alla macchina, riconnettersi eseguendo screen -D -R. Sarai nella stessa shell di prima. È possibile eseguire jobsper vedere il processo sospeso se lo si è fatto ed eseguire %1(o il rispettivo numero di lavoro) per metterlo di nuovo in primo piano.


2
Wow, non posso credere che una risposta di GNU Screen sia attualmente la più bassa. Mi sto perdendo qualcosa?
Faheem Mitha,

1
Forse! Mi sembra il migliore.
Andrew Yochum,

1
Guardando indietro, sembra chiaramente essere la soluzione più indolore, a condizione che tu possa pianificare di conseguenza e avviare i tuoi processi all'interno di un ambiente dello schermo. Comunque, l'ho resa la risposta ufficiale!
levesque

28
Penso che questo non risponda alla domanda. La domanda inizia con " Ho un programma in esecuzione ". Questa risposta presuppone che non sia ancora in esecuzione ...
Anko

sì, ha scritto chiaramente che vuole farlo entrare in una sessione sullo schermo :-)
Florian Heigl,

112

È possibile revocare la "proprietà" del programma dalla shell con il disownbuilt-in:

# press Ctrl+Z to suspend the program
bg
disown

Tuttavia, questo dice solo alla shell di non inviare un SIGHUPsegnale al programma quando la shell esce. Il programma manterrà tutte le connessioni che ha con il terminale, generalmente come flussi di input, output ed errori standard. Non è possibile ricollegarli a un altro terminale. (Lo schermo funziona emulando un terminale per ogni finestra, quindi i programmi sono collegati alla finestra dello schermo.)


È possibile ricollegare i filedescriptor a un altro file collegando il programma in un debugger (cioè usando ptrace) e facendolo chiamare open, dupe close. Ci sono alcuni strumenti che lo fanno; questo è un processo complicato e, a volte, si bloccherà invece il processo. Le possibilità includono (collegamenti raccolti dalle risposte a Come posso rinnegare un processo in esecuzione e associarlo a una nuova shell dello schermo? E posso nohup / schermare un processo già avviato? ):


disownrimuove il processo dall'elenco di controllo dei lavori.
ctrl-alt-delor,

3
Perché no disown -h?
Cees Timmerman,

@CeesTimmerman Questo lascia il lavoro nella tabella dei lavori della shell, ma qual è il vantaggio?
Gilles,

@Gilles: così puoi ancora fgo no kill, e vedere se finisce da solo.
Peter Cordes,

Quali utilità menzionate funzionano con un gruppo di processi (ad es. bzcat a.bz2 | grep text)? L'uomo per reptyrdice che non supporta lo spostamento dei processi con i bambini.
dma_k,

64

Per spostare un processo tra i terminali o ricollegare un sconosciuto, è possibile utilizzare ad esempio reptyr .


1
Sì, questo l'ha salvato, grazie! Ho letto il sito web dell'autore come funziona meglio di strumenti simili o precedenti, ad es. per i programmi ncurses.
Marcos

4
Questo e spettacolare; dovrebbe risolvere la situazione di un amico di perdere costantemente il suo lavoro eseguendolo dritto in ssh e quindi aver bisogno di salire su un treno. "Oops, ho dimenticato di usare lo schermo. Di nuovo."
Adam Katz,

3
+1 Sebbene la screenrisposta accettata sia ovviamente l'ideale, in realtà non risponde alla domanda, che richiede specificamente un modo per spostare un processo attualmente in esecuzione screeno simili. Vedi anche questa risposta: serverfault.com/a/284795
toxefa,

1
Absolute live saver. Mi ha permesso di ricollegarmi all'esecuzione di apt dist-upgrade che era in attesa della conferma dell'utente.
Andig

28

La mia soluzione preferita sta usando tmux, potresti staccare la sessione e ricollegarla in un altro terminale.

Quando ti sei disconnesso dalla sessione precedente, puoi chiudere in sicurezza il terminale; utilizzare successivamente tmux attachper tornare alla sessione, anche se si è disconnessi.


1
puoi anche condividere la tua sessione con il tuo amico e utilizzare più finestre e riquadri e molto altro ancora! Lo adoro ^ _ ^
igor

esempio di utilizzo per favore?
Vitaly Zdanevich,

21

C'è anche una piccola utility chiamata retty che ti consente di ricollegare i programmi in esecuzione su un altro terminale.


19

Non lo uso regolarmente, ma Neercs afferma di supportarlo. È un screenprogramma simile con varie funzioni fantasiose come una migliore gestione dei riquadri, ma la cosa principale che offre è la possibilità di importare un processo in un riquadro


2
Interessante. Gioca a dirty ( ptrace), ma non manipola solo i descrittori di file, ma forgia il processo. È in grado di afferrare find /, ma ha avuto un crash interattivo.
Gilles,

@Gilles Non riesco a ricordare come sia andata quando ho provato, ma non ha una grande reputazione, mi hanno detto che fallisce abbastanza regolarmente
Michael Mrozek

9

Se si desidera solo metterlo in pausa e riavviare in seguito, è possibile utilizzare killcon STOPo CONTsegnale.

Inizialmente scopri i processi con PID

$ ps aux

Quindi inviare i segnali a quel PID elencato nel processo

$ kill -STOP <PID>

$ kill -CONT <PID>

9

"injcode" di ThomasHabets sembra essere esattamente ciò di cui ho bisogno:

https://github.com/ThomasHabets/injcode

Il programma injcode consente di iniettare codice arbitrario in un processo in esecuzione, indipendentemente dal fatto che lo sapessi o meno e stavi eseguendo screen o tmux

Dal README:

Esempio 1: spostare irssi da un terminale all'altro

Magari spostalo in uno schermo.

Primo avvio irssi in un terminale.

Esegui injcode in un altro terminale: $ injcode -m retty

Ora Irssi dovrebbe essere spostato sul secondo terminale, incluso avere un nuovo terminale di controllo.


1

Questo ha funzionato per me:

  1. bg il processo
  2. jobs -l trova il numero di processo
  3. tmux avvia il gestore di finestre shell
  4. reptyr -L PROCESSNUMBER

reptyrè -Lstato necessario per farlo funzionare:

-L Like '-l', but also redirect the child's stdio to the slave.

a causa di questo errore:

$ reptyr 30622

[-] Unable to open the tty in the child.
Unable to attach to pid 30622: Permission denied

E con -L

$ reptyr -L 30622
Opened a new pty: /dev/pts/4
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.