Come si collega un terminale a un processo distaccato?


99

Ho staccato un processo dal mio terminale, in questo modo:

$ process &

Quel terminale è ormai chiuso da tempo, ma processè ancora in esecuzione e voglio inviare alcuni comandi allo stdin di quel processo. È possibile?



1
Cerca retty, neercsecc e vedere anche serverfault.com/questions/24425 , serverfault.com/questions/115998
Gilles

Risposte:


112

Sì. In primo luogo, creare una pipe: mkfifo /tmp/fifo. Usa gdb per collegarti al processo: gdb -p PID

Quindi chiudere stdin: call close (0); e riaprilo:call open ("/tmp/fifo", 0600)

Infine, scrivi via (da un terminale diverso, poiché gdb probabilmente si bloccherà):

echo blah > /tmp/fifo


6
Molto impressionante!
Samuel Edwin Ward,

1
Posso fare qualcosa di simile a reindirizzare il processo stdout su un file?
Rustyx,

@rustyx: Non testato, ma questo dovrebbe funzionare: creare un file piuttosto che un tubo, touch /tmp/thefile. Stdout è 1, quindi call close (1); Inoltre, utilizzare le autorizzazioni corrette per la scrittura: call open ("/tmp/thefile", 0400). Il echo…è, ovviamente, non è necessario.
Ansgar Esztermann,

Questo è fantastico! Sto usando questo per inviare risposte "y" o "n" a determinati processi che sono stati completamente separati. Il processo distaccato ha il suo stdout in una finestra separata. Quando eseguo questo trucco, tuttavia, vedo che non "riceve" la 'y' o 'n' non appena l'ho eco, devo uscire da gdb e staccarlo e quindi riceve tutti gli echi di conseguenza, quindi c'è un modo per eseguire ciò senza la necessità di uscire da gdb prima che il processo riceva l'input dal fifo?
krb686,

purtroppo sembra solo appeso call open("/tmp/fifo", 0600). qualsiasi aiuto sarebbe molto apprezzato
arciere il

27

Quando il terminale originale non è più accessibile ...

reptyrpotrebbe essere quello che vuoi, vedi https://serverfault.com/a/284795/187998

Citazione da lì:

Dai un'occhiata a reptyr , che fa esattamente questo. La pagina di github contiene tutte le informazioni.

reptyr - Uno strumento per i "re-ptying" programmi.

reptyr è un'utilità per prendere un programma in esecuzione esistente e collegarlo a un nuovo terminale. Ha iniziato un processo di lunga durata su ssh, ma devi partire e non vuoi interromperlo? Basta avviare una schermata, usare reptyr per afferrarla, quindi uccidere la sessione ssh e andare a casa.

USO

reptyr PID

"reptyr PID" afferrerà il processo con ID PID e lo collegherà al terminale corrente.

Dopo il collegamento, il processo prenderà l'input e scriverà l'output sul nuovo terminale, inclusi ^ C e ^ Z. (Sfortunatamente, se lo sfondo, dovrai comunque eseguire "bg" o "fg" nel vecchio terminale. Questo è probabilmente impossibile da risolvere in modo ragionevole senza patchare la shell.)


12

Sono abbastanza sicuro che non puoi.

Controlla usando ps x. Se un processo ha una ?come terminale di controllo , non è possibile inviare input per più.

9942 ?        S      0:00 tail -F /var/log/messages
9947 pts/1    S      0:00 tail -F /var/log/messages

In questo esempio, puoi inviare input per 9947fare qualcosa del genere echo "test" > /dev/pts/1. L'altro processo ( 9942) non è raggiungibile.

La prossima volta, potresti usare screen o tmux per evitare questa situazione.


5
O dtachse non hai bisogno di un tutto screen.
arte

4
Non c'è modo negli standard (POSIX, SUS), ma su molti sistemi (la maggior parte?) È possibile utilizzare i meccanismi che utilizzano i debugger. Vedi la risposta di Ansgar . Con rootte potresti persino farlo ai processi di altri utenti.
dmckee,

3
Fare echo "test" > /dev/pts/1non invierà l'input al processo 9947- produrrà la parola "test" sul terminale di quel processo.
psmears,

6

EDIT : Come ha detto Stephane Gimenez, non è così semplice. Ti consente solo di stampare su un altro terminale.

Puoi provare a scrivere in questo processo usando / proc . Dovrebbe trovarsi in / proc / pid / fd / 0 , quindi un semplice:

echo "hello" > /proc/PID/fd/0

dovrebbe farlo. Non l'ho provato, ma dovrebbe funzionare, purché questo processo abbia ancora un descrittore di file stdin valido . Puoi controllarlo con ls -lon / proc / pid / fd / .

  • se è un collegamento a / dev / null => è chiuso
  • se è un collegamento a / dev / pts / X o un socket => è aperto

Vedi nohup per maggiori dettagli su come mantenere i processi in esecuzione.


2
Non è così semplice. Ad esempio, se lo stdin è collegato a un terminale, l' echoinvio di qualcosa al dispositivo terminale stamperà semplicemente ciò che è stato scritto sul terminale, non verrà trasmesso al processo.
Stéphane Gimenez,

5

Basta terminare la riga di comando con &non distaccerà completamente il processo, ma lo eseguirà solo in background. (Con zshte puoi usarlo &!per staccarlo, altrimenti lo devi fare disownin seguito).

Quando un processo viene eseguito in background, non riceverà più input dal suo terminale di controllo. Ma puoi rimandarlo in primo piano con fge poi leggerà di nuovo l'input.

Altrimenti, non è possibile modificare esternamente i suoi descrittori di file (incluso stdin) o ricollegare un terminale di controllo perso ... a meno che non si utilizzino strumenti di debug (vedere la risposta di Ansgar o dare un'occhiata al rettycomando).


E qui c'è una domanda correlata: unix.stackexchange.com/q/17648/9426
Stéphane Gimenez

@Rogach ha dichiarato "Quel terminale è ormai chiuso da tempo".
Andcoz,

1
@andcoz: Sì, ma è stato fortunato a non aver visto il programma SIGHUP. Stavo suggerendo un metodo più sicuro.
Stéphane Gimenez,

qui, disown funziona davvero solo se prima reindirizzo stdout come con >>/dev/stderr, altrimenti, quando chiudo il terminale, finirà anche il processo "sconosciuto" .. Non l'ho mai capito davvero ...
Aquarius Power
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.