Làm thế nào để xem đầu ra của một tiến trình đang chạy trong một phiên bash khác?


199

Tôi đã để lại một đoạn script chạy trên một máy từ xa từ khi tôi làm việc tại nó. Tôi có thể kết nối qua SSH với máy với cùng một người dùng và xem tập lệnh đang chạy ps.

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

Nó chỉ đơn giản là xuất ra thiết bị xuất chuẩn trên một phiên cục bộ (Tôi đã chạy ./ipchecker.shtừ một cửa sổ thiết bị đầu cuối cục bộ, không chuyển hướng, không sử dụng screenvv).

Có cách nào từ phiên SSH tôi có thể xem đầu ra của lệnh đang chạy này (mà không dừng lại không)?

Cho đến nay, thứ tốt nhất tôi tìm thấy là sử dụng strace -p 18386nhưng tôi nhận được vô số văn bản bay lên màn hình, nó quá chi tiết. Tôi có thể dừng lại stracevà sau đó sàng lọc đầu ra và tìm văn bản được in ra thiết bị xuất chuẩn nhưng nó rất dài và khó hiểu, và rõ ràng trong khi nó dừng tôi có thể bỏ lỡ điều gì đó. Tôi muốn tìm một cách để xem đầu ra kịch bản trực tiếp như thể tôi đang làm việc tại địa phương.

Bất cứ ai có thể cải thiện về điều này? Câu trả lời rõ ràng là khởi động lại tập lệnh bằng chuyển hướng hoặc trong một screenphiên, v.v., đây không phải là tập lệnh quan trọng để tôi có thể làm điều đó. Thay vào đó, tôi thấy đây là một bài tập học vui vẻ.


Là quá trình của bạn đang chạy trong một bảng điều khiển ảo hoặc trong một môi trường giống như GUI / xterm?
jippie

4
Bạn có thể giới hạn đầu ra của strace xuống một strace -p 4232 -e write
tòa nhà

@jippie Máy đang chạy GUI đầy đủ (Linux Mynt 13, máy tính để bàn XFCE), tôi đã kích hoạt một thiết bị đầu cuối gnome.
jwbensley

3
Có ít nhất một tá câu hỏi tương tự trên trang web này. Tìm kiếm reptyr ở đây để tìm một vài trong số họ (và một câu trả lời).
Stéphane Chazelas

Câu trả lời:


180

Nếu tất cả những gì bạn muốn làm là theo dõi quá trình hiện có, bạn có thể sử dụng strace -p1234 -s9999 -e writetrong đó 1234 là ID tiến trình. ( -s9999tránh việc các chuỗi bị cắt ngắn thành 32 ký tự và writecuộc gọi hệ thống tạo ra đầu ra.) Nếu bạn chỉ muốn xem dữ liệu được ghi trên một bộ mô tả tệp cụ thể, bạn có thể sử dụng một cái gì đó như strace -p1234 -e trace= -e write=3để chỉ xem dữ liệu được ghi vào bộ mô tả tệp 3 ( -e trace=ngăn hệ thống các cuộc gọi từ được đăng nhập). Điều đó sẽ không cung cấp cho bạn đầu ra đã được sản xuất.

Nếu đầu ra đang cuộn quá nhanh, bạn có thể chuyển nó vào một máy nhắn tin như less, hoặc gửi nó đến một tệp với strace -o trace.log ….

Với nhiều chương trình, bạn có thể chuyển hướng đầu ra tiếp theo bằng hack ptrace, sang thiết bị đầu cuối hiện tại của bạn hoặc sang phiên màn hình mới. Xem Làm thế nào tôi có thể từ chối một quá trình đang chạy và liên kết nó với một vỏ màn hình mới? và các chủ đề liên kết khác.

Lưu ý rằng tùy thuộc vào cách hệ thống của bạn được thiết lập, bạn có thể cần chạy tất cả các stracelệnh này dưới dạng root ngay cả khi quy trình đang chạy dưới người dùng của bạn mà không có đặc quyền bổ sung. (Nếu quy trình đang chạy như một người dùng khác hoặc là setuid hoặc setgid, bạn sẽ cần chạy stracedưới quyền root.) Hầu hết các bản phân phối chỉ cho phép một quá trình theo dõi con của nó (điều này mang lại lợi ích bảo mật vừa phải - nó ngăn chặn một số phần mềm độc hại trực tiếp, nhưng không ngăn chặn tiêm gián tiếp bằng cách sửa đổi tập tin). Điều này được kiểm soát bởi kernel.yama.ptrace_scomesysctl.


18
Tôi không cho rằng có cách thu hẹp sản lượng xuống chỉ còn đầu ra tiêu chuẩn ?
Giô-na

3
Bạn có thể giải thích tất cả các đối số?
Người dùng

6
Có rất nhiều dấu gạch chéo ngược và số trong rất nhiều đầu ra tôi nhận được từ nodejs; Bất kỳ dẫn nào về mã hóa họ có thể được trong? Có rất nhiều văn bản đơn giản, đó là tất cả những gì tôi cần.
ThorSummoner 16/07/2015

3
"Bạn có thể giải thích tất cả các đối số?" @ Người dùng:man strace
Pistos

3
@RafaelMoni Một chương trình để làm những gì bạn yêu cầu được gọi là trình gỡ lỗi.
Gilles

139

Bạn có thể truy cập đầu ra thông qua prochệ thống tập tin.

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

1= thiết bị xuất chuẩn, = thiết bị xuất 2chuẩn


7
Nó cho tôi: 'không thể mở / Proc / <my pid> / fd / 1 để đọc: Không có thiết bị hoặc địa chỉ như vậy'.
Yaroslav Nikitenko

18
yeah <my pid> nên là id quá trình của bạn
tvlooy

29
Điều này sẽ không hoạt động nếu đầu ra sẽ chuyển sang tty (hoặc được chuyển hướng đến /dev/null) - nó sẽ chỉ hoạt động nếu đầu ra được chuyển hướng đến một tệp.
mattdm

1
Đã thử nghiệm trên Ubuntu 16.04 và nó không hoạt động. Trong một phiên tôi làm: ping google.esvà trong một phiên khác là root: tail -f /proc/`pgrep ping`/fd/2và không có gì được hiển thị.
david.perez

1
bạn đúng rồi. Bởi vì fd 1 và 2 là các liên kết tượng trưng đến thiết bị / dev / pts. Bạn không thể đuôi thiết bị pfa. Lịch trình lệnh ping của bạn như là một cronjob và sau đó làm tương tự. đuôi -f sau đó sẽ hoạt động
tvlooy

9

Trong BSD, bạn có thể sử dụng watchđể theo dõi một tty nhất định, ví dụ:

watch /dev/pts/0

Trong Linux, sẽ không thể thực hiện được nếu quá trình không được chạy dưới bộ ghép kênh trước đó như screenhoặc tmux. Xem thêm: Reptyr: Đính kèm một quy trình đang chạy với một thiết bị đầu cuối mới

Có vẻ như cách duy nhất là để gỡ lỗi quá trình (ví dụ strace, dtrace/ dtruss, gdb, lldb, vv).

Vì bạn đã sử dụng strace, để tìm nạp bất kỳ đầu ra có ý nghĩa nào, bạn cần lọc theo một biểu thức đủ điều kiện (chẳng hạn như file), sau đó phân tích đầu ra. Đây là ví dụ:

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

Những gì nó in hoạt động ghi của quá trình (1000 độ dài) được chỉ định bởi PID (sử dụng pgrepđể tìm nó theo tên), chuyển hướng lỗi tiêu chuẩn thành đầu ra (sẽ được lọc) và in chuỗi trích dẫn kép.

Nếu bạn đang xử lý đầu ra nhị phân, bạn có thể phân tích các chuỗi ký tự thoát bằng cách sử dụng read(với -r) và printf (với %b), ví dụ:

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

Kiểm tra help readthêm thông số (ví dụ -nđể in sau một số ký tự nhất định, thay vì dòng mới).

Dưới đây là ví dụ đầy đủ hơn:

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

Đối với các ví dụ sử dụng bất kỳ quy trình nào, vui lòng kiểm tra: Làm thế nào để phân tích bước trong shell thành văn bản thuần túy? tại stackoverflow


4
  1. Bạn có thể có thể lén nhìn màn hình từ xa sử dụng ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scaleở đâu localhostlà được thay thế bằng thông tin đăng nhập máy chủ từ xa của bạn và :0.0với số lượng hiển thị của GUI.

  2. Sử dụng x11vnc, là máy chủ VNC cho phiên X trên màn hình của bạn.

  3. Khi chạy trên một trong 6 bàn giao tiếp ảo sudo setterm -dump 2 -file /dev/stdout, bạn thay thế 2bằng vc thích hợp.


4

Tôi khuyên bạn nên tạo một ống có tên ( mkfifo) và sau đó ghi vào tệp đó. Sau đó, đọc từ nó. Bạn luôn có thể làm điều đó với những thứ như tail, để giảm thiểu đầu ra, v.v ... Bất cứ khi nào bạn xóa đường ống (đọc từ nó), nó sẽ bị xóa, do đó đầu ra không được bảo toàn.

Tùy chọn khác sẽ là ghi mọi thứ vào một tệp (giống như logfile) và sau đó phân tích nó bất cứ lúc nào. Đây sẽ là hành động ưa thích, nếu bạn muốn duy trì tất cả đầu ra.


3

Bạn luôn có thể khởi chạy một quá trình với nohup&

nohup rsync source_file dest_file &

Sau đó, bạn sẽ có thể kiểm tra tiến trình từ bất kỳ tty nào với:

tail -f nohup.out

Điều này làm việc tốt với tôi.


6
Câu hỏi này tôi muốn biết về cách xem đầu ra của một quy trình chạy cảnh báo, chứ không phải làm thế nào để chạy một quy trình trong nền như câu trả lời của bạn gợi ý
jwbensley

Trong thực tế, của bạn: nohup đề cập đến soi sáng cho tôi! Cảm ơn!
Nam G VU

1

Rất đơn giản để có được đầu ra sẽ ghi lại đầu ra của bạn vào một tệp và theo đuôi tệp đó.

NẾU LÀM: ./ipcheck

INSTEAD DO: ./ipcheck> [replacewithyourfilename]

Điều này sẽ tạo ra một tập tin đầu ra nơi tập lệnh của bạn được đặt. Sau đó, từ bất kỳ shell bash nào khác, bạn có thể chỉ cần theo đuôi tệp:

đuôi [replacewithyourfilename] -f


Chuyển hướng tập tin có xu hướng sử dụng bộ đệm dựa trên khối theo mặc định (xem setbuf(3)) có thể gây ra tailvấn đề.
thrig

5
Ngoài ra, điều này không giúp ích gì cho câu hỏi, đó là về cách xem đầu ra của một quy trình đã chạy, chứ không phải làm thế nào để chuyển hướng thiết bị xuất chuẩn cho một quy trình mới.
jwbensley

1

Phân tích cú pháp đầu ra của strace:

Tôi đã sử dụng câu trả lời hàng đầu (với ID tiến trình của tôi là 28223) ...

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

Để xác định rằng tôi quan tâm write(9. (Số 9 được sử dụng bên dưới, đây có thể là một tệp xử lý và có thể khác với quy trình của bạn.) Sau đó, tôi đã viết một tập lệnh Ruby nhanh để phân tích và hiển thị chúng.

Dán sau đây vào /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
}

Đừng quên chmod a+x /usr/bin/parse_strace.rb

Tôi gọi strace -xx(đầu ra hex, do đó regex khớp chính xác), đường ống (bao gồm STDERR) vào tập lệnh của tôi với 9tư cách là đối số đầu tiên.

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

Và, voila, nó xuất ra STDOUT ban đầu, dòng mới, màu sắc và tất cả!

Đính kèm để xử lý STDOUT


0

bạn không thể lấy ID tiến trình và liên lạc với nó với USR1,

$pgrep -l '^ipchecker.sh$'

trong đó in PID của tập lệnh của bạn, sau đó sử dụng nó để

$ kill -USR1 PID

Tôi hiểu rằng USR1 là tín hiệu "do người dùng xác định", nghĩa là bất kỳ ai đã tạo chương trình đều có thể sử dụng nó để "tắt" hoặc "xóa nhật ký của bạn" hoặc "in foo một nghìn lần" hoặc bất cứ điều gì.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.