Menulis ke stdin dari proses latar belakang

25

Saya menggunakan kotak Ubuntu 10,04, dan memulai server di latar belakang (myserver &) lewat ssh. Sudah berjalan dengan baik, tapi saya perlu cara untuk mendapatkan stdin server, karena satu-satunya cara untuk mengendalikan server adalah melalui metode ini.

Apakah ada cara untuk mendapatkan stdin dari proses yang sudah berjalan sehingga saya bisa menulisnya (dan semoga membaca stdout-nya)? Jelas, jika saya akan melakukan ini sekarang, saya akan memulainya dengan FIFO yang mengarahkan kembali ke stdin, tapi sayangnya sudah agak terlambat untuk itu sekarang.

Ada ide?

tajmorton
sumber
Tidak bisakah Anda membawanya kembali ke latar depan? ('jobs' akan mencantumkan proses latar belakang Anda saat ini, 'fg $ X' akan membawa pekerjaan kembali ke latar depan, ctrl + b akan menjeda pekerjaan dan mengembalikan Anda ke shell Anda, sementara 'bg' akan melanjutkan proses yang dijeda di background)
symcbean

Jawaban:

10

Anda dapat mencoba menulis ke direktori pid / proc itu. Katakanlah pid daemon Anda adalah 2000, coba tulis ke / proc / 2000 / fd / 0

katriel
sumber
Terima kasih ... Saya menemukan itu tepat setelah saya memposting ini (setelah seharian mencari - khas). Tampaknya berhasil (sejauh mengirim data ke program). Sayangnya, program tidak menerima perintah. Saya mengujinya menjalankan server di komputer lokal saya, dan tentu saja, saya melihat data muncul, tetapi program tidak mengenali perintah. Saya harus secara manual menekan enter pada terminal server, dan kemudian hanya mengatakan perintah yang tidak dikenal. Mungkin beberapa keanehan java? Saya macet ...
tajmorton
1
bagaimana dengan echo -e "something \ n"> / proc / 2000 / fd / 0?
katriel
Sebenarnya, ini tidak selalu berfungsi sebagai / proc / <pid> / fd / 0 menunjuk ke / dev / pts <beberapa angka> pada setidaknya beberapa sistem ...
bk138
Jawaban pertama untuk serverfault.com/questions/178457/… mencatat bahwa pendekatan ini tidak benar-benar berfungsi.
barrycarter
2
Ini sebenarnya tidak berfungsi. Shell Anda biasanya (ketika tidak ada pipa atau pengalihan digunakan) memulai perintah dengan deskriptor file 0melalui 2set ke file yang sama, yang biasanya adalah terminal virtual (sesuatu seperti /dev/pty/...). Perintah tersebut kemudian membaca dari FD 0dan menulis ke FD 1dan 2untuk berkomunikasi dengan terminal virtual (misalnya melalui SSH atau langsung dengan emulator terminal Anda). Jika ada proses lain mengakses file itu (misalnya melalui /proc), hal yang persis sama terjadi, yaitu menulis kepadanya menulis ke terminal dan bukan ke perintah.
Feuermurmel
29

Anda dapat memulai server Anda dengan pipa bernama (fifo) sebagai inputnya:

mkfifo /tmp/srv-input
cat > /tmp/srv-input &
echo $! > /tmp/srv-input-cat-pid
cat /tmp/srv-input | myserver &

The cat > /tmp/srv-input &penting untuk menghindari server Anda untuk menerima EOF a. Setidaknya satu proses harus memiliki fifo dibuka secara tertulis sehingga server Anda tidak menerima EOF. PID dari perintah ini disimpan dalam /tmp/srv-input-cat-pidfile untuk pembunuhan terakhir.

Dalam kasus Anda di mana Anda sudah memulai server Anda, Anda harus menggunakan debugger seperti gdbuntuk melampirkan ke proses Anda untuk mengarahkan kembali stdinke fifo:

gdb -p PID
call close(0)
call open(0, "/tmp/srv-input", 0600)

Dan kemudian lakukan sesuatu seperti di bawah ini untuk mengirim input ke server Anda (di jendela terminal lain jika perlu):

echo "command" > /tmp/srv-input

Untuk mengirim EOF ke server Anda, Anda harus mematikan cat > /tmp/srv-inputproses PID yang telah disimpan di /tmp/srv-input-cat-pid file.

Dalam kasus GDB, cukup keluar dari GDB dan EOF akan dikirim.

jfg956
sumber
1
ini adalah pendekatan yang jauh lebih portabel daripada yang dari @katriel karena / proc / 2000 / fd / 0 tidak stdin pada semua sistem.
Prior99
Trik dengan "cat> / tmp / srv-input &" menyelamatkan saya dari sakit kepala. Terima kasih!
Prior99
Bagaimana dengan mkfifo /tmp/srv-input; tail -f /tmp/srv-input | myserver &? Ini akan menjaga pipa tetap terbuka juga ...
bk138
@ bk138: menurut saya ekor harus bekerja, tetapi hanya ada satu cara untuk mengetahui dengan pasti: tes.
jfg956
tailtidak bekerja, tetapi menambahkan ini untuk menyelesaikan pekerjaan: cat /tmp/srv-input | myserver; kill -9 cat / tmp / srv-input-cat-pid` && rm / tmp / srv-input-cat * `
Thiago Macedo
4

Sama seperti di atas, tetapi 'kucing' tidak bekerja untuk saya. File mendapat EOF dan berakhir setelah mengirim satu perintah.

Ini bekerja untuk saya:

#!/bin/bash

mkfifo /tmp/srv-input
tail -f /tmp/srv-input | myserver &
Tamir
sumber