Bagaimana cara memasang terminal ke proses terpisah?

99

Saya telah memisahkan proses dari terminal saya, seperti ini:

$ process &

Terminal itu sekarang sudah lama ditutup, tetapi processmasih berjalan, dan saya ingin mengirim beberapa perintah ke stdin proses itu. Apakah itu mungkin?

Rogach
sumber

Jawaban:

112

Ya itu. Pertama, membuat pipa: mkfifo /tmp/fifo. Gunakan gdb untuk melampirkan ke proses: gdb -p PID

Stdin kemudian tutup: call close (0); dan buka lagi:call open ("/tmp/fifo", 0600)

Akhirnya, hapus (dari terminal yang berbeda, karena gdb mungkin akan hang):

echo blah > /tmp/fifo

Ansgar Esztermann
sumber
6
Sangat mengesankan!
Samuel Edwin Ward
1
Bisakah saya melakukan sesuatu yang mirip dengan mengarahkan proses stdout ke file?
rustyx
@ rustyx: Belum diuji, tapi ini harusnya berfungsi: buat file daripada pipa touch /tmp/thefile,. Stdout adalah 1, jadi call close (1); juga, menggunakan izin yang benar untuk menulis: call open ("/tmp/thefile", 0400). The echo…adalah, tentu saja, tidak diperlukan.
Ansgar Esztermann
Ini bagus! Saya menggunakan ini untuk mengirim tanggapan "y" atau "n" ke proses tertentu yang telah sepenuhnya terlepas. Proses terlepas memiliki stdout ke jendela terpisah. Namun ketika saya melakukan trik ini, saya dapat melihat bahwa itu tidak "menerima" the 'y' atau 'n' begitu saya mengulanginya, saya harus keluar dari gdb dan melepaskannya dan kemudian menerima semua gema sesuai, jadi apakah ada cara untuk melakukan ini tanpa harus berhenti gdb sebelum proses menerima input dari fifo?
krb686
sayangnya itu sepertinya bertahan call open("/tmp/fifo", 0600). bantuan apa pun akan sangat dihargai
pemanah
27

Ketika terminal asli tidak lagi dapat diakses ...

reptyrmungkin apa yang Anda inginkan, lihat https://serverfault.com/a/284795/187998

Kutipan dari sana:

Lihatlah reptyr , yang melakukan hal itu. Halaman github memiliki semua informasi.

reptyr - Alat untuk program "re-ptying".

reptyr adalah utilitas untuk mengambil program yang sedang berjalan dan melampirkannya ke terminal baru. Memulai proses yang berjalan lebih lama dari ssh, tetapi harus pergi dan tidak ingin menyela? Mulai saja layar, gunakan reptyr untuk meraihnya, lalu matikan sesi ssh dan langsung menuju rumah.

PEMAKAIAN

PID reptyr

"reptyr PID" akan mengambil proses dengan id PID dan melampirkannya ke terminal Anda saat ini.

Setelah melampirkan, proses akan mengambil input dari dan menulis output ke terminal baru, termasuk ^ C dan ^ Z. (Sayangnya, jika Anda latar belakang, Anda masih harus menjalankan "bg" atau "fg" di terminal lama. Ini kemungkinan tidak mungkin untuk diperbaiki dengan cara yang wajar tanpa menambal shell Anda.)

NiKiZe
sumber
12

Saya cukup yakin Anda tidak bisa.

Periksa menggunakan ps x. Jika suatu proses memiliki tty? sebagai pengendali , Anda tidak dapat mengirim input lagi.

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

Dalam contoh ini, Anda dapat mengirim input untuk 9947melakukan sesuatu seperti echo "test" > /dev/pts/1. Proses lainnya ( 9942) tidak dapat dijangkau.

Lain kali, Anda bisa menggunakan layar atau tmux untuk menghindari situasi ini.

andcoz
sumber
5
Atau dtachjika Anda tidak membutuhkan keseluruhan screen.
manatwork
4
Tidak ada cara dalam standar (POSIX, SUS), tetapi pada banyak (kebanyakan?) Sistem adalah mungkin menggunakan mekanisme yang digunakan para penipu. Lihat jawaban Ansgar . Dengan rootAnda bahkan bisa melakukan ini pada proses pengguna lain.
dmckee
3
Melakukan echo "test" > /dev/pts/1tidak akan mengirim input untuk diproses 9947- itu akan menampilkan kata "tes" pada terminal proses itu.
psmears
6

EDIT : Seperti yang dikatakan Stephane Gimenez, ini tidak sesederhana itu. Ini hanya memungkinkan Anda untuk mencetak ke terminal yang berbeda.

Anda dapat mencoba menulis ke proses ini menggunakan / proc . Itu harus berada di / proc / pid / fd / 0 , jadi sederhana:

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

harus melakukannya. Saya belum mencobanya, tetapi harus bekerja, selama proses ini masih memiliki deskriptor file stdin yang valid . Anda dapat memeriksanya dengan ls -ldi / proc / pid / fd / .

  • jika itu tautan ke / dev / null => ditutup
  • jika itu tautan ke / dev / pts / X atau soket => terbuka

Lihat nohup untuk detail lebih lanjut tentang cara menjaga proses berjalan.

Coren
sumber
2
Tidak sesederhana itu. Sebagai contoh, Jika stdin ditautkan ke terminal, memasukkan echosesuatu ke perangkat terminal hanya akan mencetak apa yang Anda tulis di terminal, itu tidak akan dikirim ke proses.
Stéphane Gimenez
5

Hanya mengakhiri baris perintah dengan &tidak akan sepenuhnya melepaskan proses, itu hanya akan menjalankannya di latar belakang. (Dengan zshAnda dapat menggunakan &!untuk benar-benar melepaskannya, kalau tidak Anda harus melakukannya disownnanti).

Ketika suatu proses berjalan di latar belakang, itu tidak akan menerima input dari terminal pengendali nya lagi. Tetapi Anda dapat mengirimnya kembali ke latar depan fgdan kemudian akan membaca input lagi.

Kalau tidak, tidak mungkin untuk mengubah file eksternal yang diajukan (termasuk stdin) atau untuk memasang kembali terminal pengendali yang hilang ... kecuali Anda menggunakan alat debugging (lihat jawaban Ansgar , atau lihat rettyperintah).

Stéphane Gimenez
sumber
Dan ada pertanyaan terkait di sini: unix.stackexchange.com/q/17648/9426
Stéphane Gimenez
@Rogach menyatakan "Terminal itu sekarang sudah lama ditutup".
andcoz
1
@andcoz: Ya tapi dia beruntung programnya belum DIJUAL. Saya menyarankan metode yang lebih aman.
Stéphane Gimenez
di sini, penolakan hanya benar-benar berfungsi jika saya mengarahkan ulang stdout seperti dengan >>/dev/stderr, jika tidak, ketika saya menutup terminal, proses "pembatalan" akan berakhir juga .. Saya tidak pernah benar-benar memahami ini ..
Aquarius Power