2009-02-27 29 views
101

Trong trình bao, bạn có thể thực hiện chuyển hướng, ><, v.v., nhưng SAU KHI một chương trình được bắt đầu?Chuyển hướng STDERR/STDOUT của một tiến trình SAU KHI nó được bắt đầu, sử dụng dòng lệnh?

Dưới đây là cách tôi đặt câu hỏi này, một chương trình chạy trong nền của thiết bị đầu cuối của tôi tiếp tục xuất ra văn bản gây phiền nhiễu. Đó là một quá trình quan trọng vì vậy tôi phải mở một trình bao khác để tránh văn bản. Tôi muốn có thể >/dev/null hoặc một số chuyển hướng khác để tôi có thể tiếp tục làm việc trong cùng một trình bao.

+0

Tôi biết cách dễ nhất để chuyển hướng STDOUT/thiết bị lỗi chuẩn là để dup2 file descriptor của họ TRƯỚC forking. Đây là một thực hành khá tiêu chuẩn, và có lẽ cách vỏ thực hiện nó ngay bây giờ.Không chắc chắn nếu điều đó đưa ra một câu trả lời, nhưng tôi nghĩ nó làm giảm cơ hội có được một câu trả lời hay. –

+1

[reptyr] (https://github.com/nelhage/reptyr) – Louis

Trả lời

104

ngắn của đóng và mở lại tty của bạn (ví dụ: đăng nhập tắt và bật lại, mà cũng có thể chấm dứt một số các quá trình nền của bạn trong quá trình này), bạn chỉ có một sự lựa chọn trái:

  • gắn với quá trình trong câu hỏi sử dụng gdb, và chạy:
    • p dup2 (open ("/ dev/null", 0), 1)
    • p dup2 (open ("/ dev/null", 0), 2)
    • tách
    • bỏ

ví dụ .:

$ tail -f /var/log/lastlog & 
[1] 5636 

$ ls -l /proc/5636/fd 
total 0 
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0 
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/pts/0 
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/pts/0 
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog 

$ gdb -p 5636 
GNU gdb 6.8-debian 
Copyright (C) 2008 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "x86_64-linux-gnu". 
Attaching to process 5636 
Reading symbols from /usr/bin/tail...(no debugging symbols found)...done. 
Reading symbols from /lib/librt.so.1...(no debugging symbols found)...done. 
Loaded symbols for /lib/librt.so.1 
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done. 
Loaded symbols for /lib/libc.so.6 
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done. 
[Thread debugging using libthread_db enabled] 
[New Thread 0x7f3c8f5a66e0 (LWP 5636)] 
Loaded symbols for /lib/libpthread.so.0 
Reading symbols from /lib/ld-linux-x86-64.so.2...(no debugging symbols found)...done. 
Loaded symbols for /lib64/ld-linux-x86-64.so.2 

(no debugging symbols found) 
0x00007f3c8eec7b50 in nanosleep() from /lib/libc.so.6 

(gdb) p dup2(open("/dev/null",0),1) 
[Switching to Thread 0x7f3c8f5a66e0 (LWP 5636)] 
$1 = 1 

(gdb) p dup2(open("/dev/null",0),2) 
$2 = 2 

(gdb) detach 
Detaching from program: /usr/bin/tail, process 5636 

(gdb) quit 

$ ls -l /proc/5636/fd 
total 0 
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0 
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/null 
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/null 
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog 
lr-x------ 1 myuser myuser 64 Feb 27 07:36 4 -> /dev/null 
lr-x------ 1 myuser myuser 64 Feb 27 07:36 5 -> /dev/null 

Bạn cũng có thể xem xét:

  • sử dụng screen; màn hình cung cấp một số TTY ảo bạn có thể chuyển đổi giữa mà không phải mở SSH/telnet mới/v.v., phiên
  • sử dụng nohup; điều này cho phép bạn đóng và mở lại phiên của bạn mà không làm mất bất kỳ quá trình nền nào trong quy trình ....
+1

Câu trả lời gdb của bạn không hoạt động với tệp đuôi -f, và nó không hoạt động với một chương trình thử nghiệm trong c được biên dịch với gcc -ggdb thực hiện một printf mỗi giây. Ngoài ra tiếp theo làm cho nó không thể chạy lệnh gdb nhiều hơn, lệnh sẽ được tách ra, sau đó bỏ thuốc lá. –

+0

Đúng về tách ra, đó là 2AM. :) Chính xác thì không làm việc với giải pháp gdb? – vladr

+0

Điều xấu của tôi, không chỉ tôi đã gặp phải/tách sai, nhưng dup2 của tôi đã được đổi chỗ. Nó sẽ hoạt động ngay bây giờ. – vladr

3

Không phải là câu trả lời trực tiếp cho câu hỏi của bạn, nhưng đó là một kỹ thuật tôi đã tìm thấy hữu ích trong vài ngày qua: Chạy lệnh ban đầu bằng 'màn hình', sau đó tách ra.

53

này sẽ làm:

strace -ewrite -p $PID 

Nó không phải là sạch (cho thấy dòng như: write(#,<text you want to see>)), nhưng các công trình!


Bạn cũng có thể không thích thực tế là đối số được viết tắt. Để kiểm soát việc sử dụng thông số -s đặt độ dài tối đa của chuỗi được hiển thị.

Nó bắt tất cả các con suối, vì vậy bạn có thể muốn lọc nào đó:

strace -ewrite -p $PID 2>&1 | grep "write(1" 

chỉ hiển thị mô tả 1 cuộc gọi. 2>&1 là chuyển hướng STDERR sang STDOUT, theo mặc định, strace ghi vào STDERR.

+0

Đây là một giải pháp tuyệt vời. –

+6

Đây không phải là những gì mà OP yêu cầu. OP được yêu cầu REDIRECT ra khỏi TTY, không chặn. Ngoài ra, trên một số nền tảng strace/giàn sẽ chèn khoảng trắng giữa các ký tự dòng bị chặn và/hoặc thoát khỏi non-ASCII, và bạn cũng sẽ phải xử lý các quá trình đó. – vladr

+3

Có, điều này làm điều một phần - nhưng đối với một số người đọc câu hỏi này thì tất cả những gì họ cần - để xem điều gì đang xảy ra trong một chương trình bị nhầm lẫn chạy để ghi vào null hoặc trên bàn điều khiển khác. Tôi tìm thấy nó sau khi tìm thấy câu hỏi này trong quá trình và nghĩ rằng đó là một hack tốt đẹp (ít nhất là đối với tôi). VÀ một số ít người thấy nó hữu ích nếu mắt tôi không làm tôi mất;) – naugtur

14

Chuyển đầu ra từ một quá trình đang chạy khác bị đầu cuối, tập tin hoặc màn hình:

tty 
ls -l /proc/20818/fd 
gdb -p 20818 

Bên gdb:

p close(1) 
p open("/dev/pts/4", 1) 
p close(2) 
p open("/tmp/myerrlog", 1) 
q 

Tách rời một quá trình chạy từ bash thiết bị đầu cuối và giữ cho nó sống :

[Ctrl+z] 
bg %1 && disown %1 
[Ctrl+d] 

Giải thích:

20818 - chỉ là một ví dụ về chạy quá trình pid
p - in kết quả của lệnh gdb
gần (1) - đầu ra tiêu chuẩn chặt chẽ
/dev/pts/4 - thiết bị đầu cuối để viết thư cho
gần (2) - đầu ra lỗi gần
/tmp/myerrlog - tập tin để viết thư cho
q - bỏ gdb
bg% 1 - chạy ngừng công việc 1 trên nền
disown% 1 - tách công việc 1 từ thiết bị đầu cuối

+1

Điều này sẽ không hoạt động nếu 'stdin' (bộ mô tả tập tin' 0') bị đóng. – pabouk

+0

Điều này đã cứu ngày của tôi. Tôi đã có một chạy trong một ssl-phiên tham gia một giờ cho 10% đầu tiên và tôi thực sự không muốn giữ máy tính xách tay của tôi chạy thêm 10 giờ nữa. Nhưng tôi có quyền giả định chuyển hướng của bạn cho stderr nên đọc 'p mở ("/tmp/myerrlog ", 2)' ? –

+0

Đã xảy ra sự cố rất nhỏ khi chạy trên CentOS 6 - tệp "/ tmp/myerrlog" đã tồn tại. Đó là tầm thường để tạo ra nó với liên lạc, tất nhiên. – ebneter

18

riffing tắt vladr của (và những người khác) nghiên cứu xuất sắc:

tạo ra hai tập tin sau trong cùng một thư mục, một cái gì đó trong đường dẫn của bạn, nói $ HOME/bin:

silence.gdb, chứa (từ câu trả lời của vladr):


p dup2(open("/dev/null",0),1) 
p dup2(open("/dev/null",0),2) 
detach 
quit 

và im lặng, bao gồm:


#!/bin/sh 
if [ "$0" -a "$1" ]; then 
gdb -p $1 -x $0.gdb 
else 
echo Must specify PID of process to silence >&2 
fi 

chmod +x ~/bin/silence # make the script executable 

Bây giờ, lần sau bạn quên chuyển hướng firefox, và thiết bị đầu cuối của bạn bắt đầu lộn xộn với thông báo không thể tránh khỏi "(firefox-bin: 5117): Gdk-CẢNH BÁO **: XID va chạm, gặp sự cố":


ps # look for process xulrunner-stub (in this case we saw the PID in the error above) 
silence 5117 # run the script, using PID we found 

Bạn cũng có thể chuyển hướng đầu ra của gdb tới/dev/null nếu bạn không muốn xem nó.

+1

gdb của tôi (v7.2) có một tùy chọn tiện dụng '--batch-silent' ngăn chặn đầu ra và không đổ bạn vào bàn điều khiển gdb nếu có điều gì đó sai (ví dụ như quá trình bị thiếu). BTW, '$!' Đề cập đến công việc nền gần đây nhất, nhưng tôi không nghĩ rằng nó có thể được sử dụng trong chính kịch bản. Tôi sử dụng bí danh: 'alias silencebg = 'silence $!'' – seanf

2

này được bash script phần dựa trên câu trả lời trước, mà chuyển hướng tập tin đăng nhập trong thời gian thực của một quá trình mở, nó được sử dụng như postscript trong logrotate quá trình

#!/bin/bash 

pid=$(cat /var/run/app/app.pid) 
logFile="/var/log/app.log" 

reloadLog() 
{ 
    getStatus 
    if [ "$pid" = "" ]; then 
     showStatus 
    else 
     gdb -p $pid >/dev/null 2>&1 <<LOADLOG 
p close(1) 
p open("$logFile", 1) 
p close(2) 
p open("$logFile", 1) 
q 
LOADLOG 
     LOG_FILE=$(ls /proc/${pid}/fd -l | fgrep " 1 -> " | awk '{print $11}') 
     echo "log file set to $LOG_FILE" 
    fi 
} 

reloadLog 
Các vấn đề liên quan