Bagaimana cara melihat output dari proses yang berjalan di sesi bash lain?

199

Saya telah meninggalkan skrip berjalan pada mesin jarak jauh dari ketika saya bekerja secara lokal di sana. Saya dapat terhubung melalui SSH ke mesin sebagai pengguna yang sama dan melihat skrip berjalan ps.

$ ps aux | grep ipcheck
myuser  18386  0.0  0.0  18460  3476 pts/0    S+   Dec14   1:11 /bin/bash ./ipchecker.sh

Ini hanya keluaran ke stdout pada sesi lokal (saya berlari ./ipchecker.shmembentuk jendela terminal lokal, tidak ada redirection, tidak ada penggunaan screendll).

Adakah dari sesi SSH saya bisa melihat output dari perintah yang sedang berjalan ini (tanpa menghentikannya)?

Sejauh ini yang terbaik yang saya temukan adalah menggunakan strace -p 18386tetapi saya mendapatkan gerombolan teks terbang di layar, terlalu rinci. Saya bisa berhenti stracedan kemudian menyaring keluaran dan menemukan teks membawa dicetak ke stdout tetapi sangat panjang dan membingungkan, dan jelas sementara itu berhenti saya mungkin kehilangan sesuatu. Saya ingin menemukan cara untuk melihat output skrip hidup seolah-olah saya bekerja secara lokal.

Adakah yang bisa memperbaiki ini? Jawaban yang jelas adalah memulai kembali skrip dengan pengalihan atau dalam screensesi dll, ini bukan skrip misi kritis sehingga saya bisa melakukannya. Namun, saya melihat ini sebagai latihan belajar yang menyenangkan.

jwbensley
sumber
Apakah proses Anda berjalan di konsol virtual atau di lingkungan seperti GUI / xterm?
jippie
4
Anda dapat membatasi output dari strace ke satu syscall:strace -p 4232 -e write
otokan
@ jippie Mesin ini menjalankan GUI penuh (Linux Mynt 13, desktop XFCE), saya menyalakan terminal gnome.
jwbensley
3
Setidaknya ada selusin pertanyaan serupa di situs ini. Cari reptyr di sini untuk menemukan beberapa dari mereka (dan jawabannya).
Stéphane Chazelas

Jawaban:

180

Jika semua yang ingin Anda lakukan adalah memata-matai proses yang ada, Anda dapat menggunakan di strace -p1234 -s9999 -e writemana 1234 adalah ID proses. ( -s9999menghindari string terpotong menjadi 32 karakter, dan writesystem call yang menghasilkan output.) Jika Anda hanya ingin melihat data yang ditulis pada deskriptor file tertentu, Anda dapat menggunakan sesuatu seperti strace -p1234 -e trace= -e write=3hanya melihat data yang ditulis ke deskriptor file 3 ( -e trace=mencegah sistem panggilan agar tidak dicatat). Itu tidak akan memberi Anda output yang sudah diproduksi.

Jika hasilnya terlalu cepat, Anda dapat lessmengirimnya ke pager seperti , atau mengirimnya ke file strace -o trace.log ….

Dengan banyak program, Anda dapat mengalihkan output berikutnya dengan hack ptrace, baik ke terminal Anda saat ini atau ke sesi layar baru. Lihat Bagaimana saya bisa menolak proses yang sedang berjalan dan menghubungkannya dengan shell layar baru? dan utas terkait lainnya.

Perhatikan bahwa tergantung pada bagaimana sistem Anda diatur, Anda mungkin perlu menjalankan semua straceperintah ini sebagai root bahkan jika proses berjalan di bawah pengguna Anda tanpa hak istimewa tambahan. (Jika proses berjalan sebagai pengguna yang berbeda atau setuid atau setgid, Anda harus menjalankannya stracesebagai root.) Sebagian besar distribusi hanya memungkinkan proses untuk melacak anak-anaknya (ini memberikan manfaat keamanan moderat - ini mencegah beberapa injeksi malware langsung, tetapi tidak mencegah injeksi tidak langsung dengan memodifikasi file). Ini dikendalikan oleh kernel.yama.ptrace_scomesysctl.

Gilles
sumber
18
Saya tidak mengira ada cara untuk mempersempit output hanya ke output standar ?
Jonah
3
Bisakah Anda menjelaskan semua argumen?
Pengguna
6
Ada banyak garis miring terbalik dan angka dalam banyak output yang saya dapatkan dari nodejs; Adakah petunjuk tentang pengkodean apa yang mungkin mereka lakukan? Ada banyak teks biasa juga, yang saya butuhkan.
ThorSummoner
3
"Bisakah kamu menjelaskan semua argumen?" @ Pengguna:man strace
Pistos
3
@ RafaelMoni Suatu program untuk melakukan apa yang Anda minta disebut sebagai debugger.
Gilles
139

Anda dapat mengakses output melalui sistem procfile.

tail -f /proc/<pid>/fd/1

1= stdout, 2= stderr

tvlooy
sumber
7
Ini memberi saya: 'tidak dapat membuka / proc / <my pid> / fd / 1 untuk membaca: Tidak ada perangkat atau alamat seperti itu'.
Yaroslav Nikitenko
18
yeah <pid saya> harus menjadi id proses Anda
tvlooy
29
Ini tidak akan berfungsi jika output menuju tty (atau dialihkan ke /dev/null) - itu hanya akan berfungsi jika output diarahkan ke file.
mattdm
1
Diuji pada Ubuntu 16.04 dan tidak berhasil. Dalam sesi saya lakukan: ping google.esdan yang lain sebagai root: tail -f /proc/`pgrep ping`/fd/2dan tidak ada yang ditampilkan.
david.perez
1
kamu benar. Karena fd 1 dan 2 adalah symlink ke perangkat / dev / pts. Anda tidak dapat mengekor perangkat -fa Poin. Jadwalkan perintah ping Anda sebagai cronjob dan kemudian lakukan hal yang sama. tail -f kemudian akan bekerja
tvlooy
9

Dalam BSD, Anda dapat menggunakan watchpengintai yang diberikan, misalnya

watch /dev/pts/0

Di Linux, itu tidak akan mungkin jika proses tidak berjalan di bawah multiplexer sebelumnya seperti screenatau tmux. Lihat juga: Reptyr: Lampirkan Proses Berjalan ke Terminal Baru

Tampaknya satu-satunya cara adalah untuk debug proses (misalnya strace, dtrace/ dtruss, gdb, lldb, dll).

Karena Anda telah menggunakan strace, untuk mengambil output yang berarti, Anda perlu memfilter dengan ekspresi yang memenuhi syarat (seperti file), lalu parsing output. Berikut ini contohnya:

strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'

Apa yang dilakukannya mencetak operasi tulis dari proses (panjang 1000) yang ditentukan oleh PID (digunakan pgrepuntuk menemukannya berdasarkan nama), mengarahkan ulang kesalahan standar menjadi output (untuk difilter), dan mencetak string yang dikutip ganda.

Jika Anda berurusan dengan output biner, Anda dapat mengurai karakter urutan sekuens dengan menggunakan read(with -r) dan printf (with %b), misalnya

while read -r -t1 line; do printf "%b" $line; done

Periksa help readlebih banyak parameter (misalnya -nuntuk mencetak setelah sejumlah karakter, daripada baris baru).

Berikut ini contoh yang lebih lengkap:

strace -e trace=write -s1000 -fp 18386 2>&1 \
| grep --line-buffered -o '".\+[^"]"' \
| grep --line-buffered -o '[^"]\+[^"]' \
| while read -r line; do
  printf "%b" $line;
done

Untuk contoh yang menggunakan proses apa pun, harap periksa: Bagaimana cara mengurai strace in shell ke teks biasa? di stackoverflow

kenorb
sumber
4
  1. Anda mungkin dapat mengintip layar jauh menggunakan ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scaletempat localhostyang akan diganti oleh kredensial login server jarak jauh Anda dan :0.0dengan nomor tampilan GUI Anda.

  2. Gunakan x11vnc, yang merupakan server VNC untuk sesi X layar Anda.

  3. Saat menjalankan pada salah satu dari 6 konsol virtual coba sudo setterm -dump 2 -file /dev/stdout, di mana Anda ganti 2dengan vc yang sesuai.

jippie
sumber
4

Saya akan menyarankan untuk membuat pipa bernama ( mkfifo) dan kemudian menulis ke file itu. Kemudian, bacalah darinya. Anda selalu dapat melakukannya dengan hal-hal seperti tail, untuk meminimalkan output, dll. Setiap kali Anda membersihkan pipa (baca darinya), itu akan dihapus, sehingga output tidak dipertahankan.

Pilihan lainnya adalah menulis semuanya ke file (seperti logfile) dan kemudian menganalisanya kapan saja. Ini akan menjadi tindakan yang disukai, jika Anda ingin mempertahankan semua hasil.

polemon
sumber
3

Anda selalu dapat meluncurkan proses dengan nohup dan &

nohup rsync source_file dest_file &

Kemudian, Anda dapat memeriksa progres dari tty manapun dengan:

tail -f nohup.out

Ini berfungsi baik untuk saya.

Pablo Luna
sumber
6
Pertanyaan ini saya akan tentang bagaimana cara melihat output dari proses berjalan waspada, bukan bagaimana menjalankan proses di latar belakang seperti jawaban Anda menyarankan
jwbensley
Bahkan, Anda: menyebutkan nohup mencerahkan saya! Terima kasih!
Nam G VU
1

Cara yang sangat sederhana untuk mendapatkan output akan menangkap output Anda ke file dan tailing file itu.

JIKA LAKUKAN: ./ipcheck

BUKAN INSTEAD: ./ipcheck> [replacewithnamafileAnda]

Ini akan membuat file output di mana skrip Anda berada. Kemudian dari bash shell lain Anda cukup mengekor file:

tail [replacewithyourfilename] -f

Tuan Allen
sumber
Pengalihan file cenderung menggunakan buffering berbasis blok secara default (lihat setbuf(3)) yang mungkin membuat tailmasalah.
thrig
5
Juga ini tidak membantu dengan pertanyaan, yaitu tentang bagaimana melihat output dari proses yang sudah berjalan, bukan bagaimana mengarahkan ulang stdout untuk proses baru.
jwbensley
1

Parsing output dari strace:

Saya menggunakan jawaban teratas (dengan ID proses saya 28.223) ...

> sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...

Untuk menentukan bahwa saya peduli write(9. (Angka 9 digunakan di bawah, ini mungkin merupakan pegangan file dan mungkin berbeda untuk proses Anda.) Lalu saya menulis skrip Ruby cepat untuk menguraikan dan menampilkannya.

Rekatkan yang berikut ke dalam /usr/bin/parse_strace.rb

#!/usr/bin/ruby

num = ARGV[0]
STDIN.each { |line|
  if (line.match(/write\(#{ num },\s*"(.*?)"/)) then
    puts $1.split('\x').map { |s| s.to_i(16).chr }.join()
  end
}

Jangan lupa chmod a+x /usr/bin/parse_strace.rb

Saya memohon strace -xx(output hex, sehingga regex cocok dengan benar), pemipaan (termasuk STDERR) ke skrip saya dengan 9sebagai argumen pertama.

sudo sh -c 'strace -xx -p28223 -s9999 -e write 2>&1 | parse_strace.rb 9'

Dan, voila, ini mengeluarkan STDOUT asli, baris baru, warna, dan semuanya!

Melampirkan untuk memproses STDOUT

Jeff Ward
sumber
0

Anda tidak bisa mendapatkan ID proses dan berkomunikasi dengannya dengan USR1,

$pgrep -l '^ipchecker.sh$'

yang mencetak PID skrip Anda, lalu menggunakannya untuk

$ kill -USR1 PID

Saya mengerti bahwa USR1 adalah sinyal "yang ditentukan pengguna", yang berarti bahwa siapa pun yang membuat program dapat menggunakannya untuk berarti "mematikan" atau "membuang log Anda" atau "mencetak foo seribu kali" atau apa pun.

Saeed
sumber