Chuyển hướng stderr từ một tập lệnh đã chạy


14

Tôi đã chạy một kịch bản trong vài ngày nay. Tôi đã chuyển hướng thiết bị xuất chuẩn $HOME/mylog, nhưng không chuyển hướng stderr vì tôi nghĩ sẽ không có gì trên đó. Đột nhiên, hàng ngàn dòng bắt đầu xuất hiện trên stderr, vì vậy tôi đã đình chỉ công việc. Có cách nào để tôi có thể chuyển hướng stderr $HOME/myerrtừ bây giờ mà không cần phải khởi động lại tập lệnh không?

Tôi có quyền truy cập sudo trên hộp và đó là OS X.

Có lẽ một cái gì đó sử dụng bẫy dtools?

Tôi không thể mất công việc mà kịch bản đã thực hiện cho đến nay và khởi động lại từ đầu. Có cách nào để "kết xuất các đối tượng trong bộ nhớ" trên đĩa, đóng băng chương trình, chỉnh sửa các biến (ví dụ: mô tả tệp) và tiếp tục với bối cảnh mới không?


Câu trả lời:


12

Tôi nghĩ có thể nếu bạn đính kèm quy trình của trình thông dịch liên quan vào gdb. Tôi đã thử nó với perl one-liner này

 perl -e 'do { print "x\n"; sleep(1) } while(1)'

và nó hoạt động nhưng không may với một tập lệnh bash tương tự.


Trước hết, bạn phải tìm ra PID của quá trình đó có đầu ra mà bạn muốn nắm bắt. Sau đó bắt đầu gdbtrong một thiết bị đầu cuối khác và thực hiện các lệnh gdb sau

attach PID
call close(2)
call open("/abs/olu/te/path/filename", 65, 384)
detach PID

sau đó toàn bộ dữ liệu được ghi vào stderrđược chuyển hướng đến /abs/olu/te/path/filename, kể từ đó

  • attach PID đính kèm tiến trình vào gdb và dừng nó lại
  • call close(2)đóng stderrfiledescriptor của quá trình (đối stdoutvới filedescriptor là 1)
  • call open(...) mở một tệp mới và lấy số nguyên không sử dụng thấp nhất cho filedescriptor mới được tạo và
  • detach PID tiếp tục quá trình

Ít nhất là trên máy của tôi. Hai dòng đầu tiên tương thích POSIX nhưng không phải là dòng thứ ba.

Đối số thứ hai và thứ ba của opendòng thứ ba được ghi lại trong man 2 open. Trong trường hợp của tôi 65 có nghĩa là opennên tạo tệp và mở tệp chỉ ghi tức là O_WRONLY | O_CREAT(được xác định trong fcntl.h). Đối số thứ ba cho biết mở để tạo tệp với quyền đọc và ghi cho người dùng tức là S_IWUSR | S_IRUSR(được xác định trong sys/stat.h). Vì vậy, có thể bạn phải tự mình tìm ra các giá trị phù hợp trên máy của mình.


Điều này làm việc rất tuyệt vời ... mũ ra !!
Robottinosino

8

Đây là một câu trả lời thô thiển và tôi hy vọng ai đó sẽ làm tốt hơn, nhưng nếu không có ý tưởng nào khác xuất hiện, hãy đính kèm gdb và buộc quá trình thực hiện một vài tòa nhà:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c

Tiện lợi Tôi không biết gdb có thể làm điều đó. Có cách nào để buộc nó vào một số mô tả tập tin cụ thể không? Giống như nói nếu FD 1 không được sử dụng, và open()lấy FD 1? Hay bạn chỉ phải gọi dup()một vài lần?
Patrick

p open("errfile", O_WRONLY)thực sự làm việc trên máy của bạn?
dùng114632

Bạn có thể dính vào một p dup2(xxx, 2)và sau đó p close(xxx)ở đâu xxxlà giá trị trả về của open. Đây là công cụ khó, tốt hơn là không sử dụng các lệnh này trong một quy trình dài cho đến khi bạn chắc chắn không có lựa chọn nào khác.
Alan Curry

@ user1146332 nó đã làm khi tôi dùng thử vì tôi đã sử dụng /dev/nullnhư errfilevậy nên tôi không cần O_CREAT. Và O_WRONLYlà một macro, nó có mở rộng hay không phụ thuộc vào việc gdb có dừng quá trình tại một dòng có biểu tượng gỡ lỗi hay không và macro được xác định. Việc tiêm mã vào một quy trình với gdb là nguy hiểm và không ai nên sao chép các lệnh này mà không hiểu chúng.
Alan Curry

@AlanCurry Tôi không nghĩ rằng gdb mở rộng macro nếu có thông tin gỡ lỗi chung. Bạn phải biên dịch các nguồn với các cờ đặc biệt (xem tại đây ). Bên cạnh đó, rất hiếm khi một chương trình thực thi tùy ý trên hệ thống của bạn có thông tin gỡ lỗi được bao gồm (hãy để anlone thông tin được mở rộng với thông tin vĩ mô). Nhưng tôi đồng ý với bạn rằng việc tiêm mã thường không được khuyến khích, nhưng có thể có trường hợp bạn được hưởng lợi.
dùng1146332
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.