2010-07-26 22 views
20

Tôi đã có một kịch bản như:bash: Quá trình exec'd lực để có stdout unbuffered

#!/bin/bash 
exec /usr/bin/some_binary > /tmp/my.log 2>&1 

Vấn đề là some_binary gửi tất cả các ghi chép của mình cho stdout, và đệm làm cho nó vì vậy mà tôi chỉ nhìn thấy đầu ra theo khối của một vài dòng. Điều này là khó chịu khi một cái gì đó bị mắc kẹt và tôi cần phải xem những gì dòng cuối cùng nói.

Có cách nào để làm cho stdout không bị cản trở trước khi tôi thực hiện điều đó sẽ ảnh hưởng đến some_binary để nó có đăng nhập hữu ích hơn?

(Kịch bản wrapper chỉ thiết lập một vài biến môi trường trước khi exec, do đó, một giải pháp trong perl hoặc python cũng sẽ là khả thi.)

+5

Câu trả lời của Dennis là * chính xác * đúng. Đây là lý do tại sao. Các chương trình trên Unix sử dụng stdio C cho đầu ra sẽ đệm khi đầu ra không đi đến một thiết bị đầu cuối (tăng hiệu suất rất nhiều) trừ khi được yêu cầu không phải với 'setvbuf'; hầu như không ai làm phiền điều đó. Hệ thống 'expect' (trong đó' unbuffer' là một ứng dụng tầm thường) sử dụng phép màu đen với các thiết bị đầu cuối giả Unix (ptys) để chạy các chương trình với một thiết bị đầu cuối không phải là đầu cuối thực để chương trình gói không đệm đầu ra của nó. Đó là thông minh, nhưng được cảnh báo: hầu hết các hệ thống chỉ có một số lượng giới hạn ptys; một chương trình tự nhiên không bị chặn thì tốt hơn. –

+0

BTW, điều này không hoạt động tốt trên Windows. Đó là bởi vì kỳ vọng trên nền tảng đó sử dụng phép thuật gỡ lỗi thay vì ma thuật đầu cuối (vì đây là một khu vực mà Windows có * rất * khác nhau). –

+0

Cảm ơn. Tôi đã quyết định chọn cách sửa đổi 'some_binary' để làm điều đúng đắn thay vì dựa vào ma thuật đen. 'expect' là tuyệt vời, nhưng tôi không muốn nó ở đây ... – bstpierre

Trả lời

13

Bạn có thể thấy rằng kịch bản unbuffer mà đi kèm với expect có thể giúp đỡ.

+0

Không hoạt động với' echo -n .' hoặc 'prinff". "' mà tôi cần trong trường hợp của tôi để hiển thị thanh tiến trình trong bash – Davide

+0

Xem cũng: http://stackoverflow.com/questions/1401002/trick-an-application-into-thinking-its-stdin-is-interactive-not-a-pipe –

11

Một số chương trình dòng lệnh có tùy chọn để sửa đổi hành vi lưu vào bộ đệm luồng. Vì vậy, đó là con đường để đi nếu nguồn C có sẵn ...

# two command options ... 
man file | less -p '--no-buffer' 
man grep | less -p '--line-buffered' 

# ... and their respective source code 

# from: http://www.opensource.apple.com/source/file/file-6.2.1/file/src/file.c 
if(nobuffer) 
    (void) fflush(stdout); 

# from: http://www.opensource.apple.com/source/grep/grep-28/grep/src/grep.c 
if (line_buffered) 
    fflush (stdout); 

Là một thay thế cho việc sử dụng mong đợi của kịch bản unbuffer hoặc sửa đổi mã nguồn của chương trình, bạn cũng có thể cố gắng sử dụng kịch bản (1) để tránh stdout trục trặc gây ra bởi một ống:

Xem: Trick an application into thinking its stdin is interactive, not a pipe

# Linux 
script -c "[executable string]" /dev/null 

# FreeBSD, Mac OS X 
script -q /dev/null "[executable string]" 
+1

Trên Mac OS X, bởi vì "tập lệnh" có thể thay đổi trả lại mã từ "\ n" đến "\ r \ n", tôi cần chạy như sau: lệnh 'script -q/dev/null ... | perl -pe 's/\ n/\ r \ n/g'' –

26

GNU coreutils-8,5 cũng có stdbuf lệnh để sửa đổi I/O dòng đệm.

http://www.pixelbeat.org/programming/stdio_buffering/

Vì vậy, trong trường hợp ví dụ của bạn, bạn chỉ cần gọi:

exec stdbuf -oL /usr/bin/some_binary > /tmp/my.log 2>&1 

này sẽ cho phép văn bản xuất hiện ngay lập tức line-by-line (một lần một dòng được hoàn thành với end-of- dòng "\n" ký tự trong C). Nếu bạn thực sự muốn đầu ra ngay lập tức, hãy sử dụng -o0 để thay thế.

Cách này có thể hấp dẫn hơn nếu bạn không muốn giới thiệu sự phụ thuộc vào expect qua lệnh unbuffer. Mặt khác, cách unbuffer là cần thiết nếu bạn phải đánh lừa some_binary để nghĩ rằng nó đang đối mặt với một đầu ra tiêu chuẩn thực tế tty.

2

GNU Coreutils-8 bao gồm một chương trình được gọi là stdbuf mà về cơ bản thực hiện thủ thuật LD_PRELOAD. Nó hoạt động trên Linux và được báo cáo hoạt động trên các hệ thống BSD.

2

tôi scoured internets cho một câu trả lời, và không ai trong số này làm việc cho uniq mà là quá bướng bỉnh để đệm tất cả mọi thứ trừ stdbuf:

{piped_command_here} | stdbuf -oL uniq | {more_piped_command_here}

1

Một biến môi trường có thể thiết lập các thiết bị đầu cuối chế độ IO để unbuffered .

xuất khẩu NSUnbufferedIO = YES

này sẽ thiết lập các thiết bị đầu cuối không có bộ đệm cho cả C và Ojective-C lệnh đầu ra thiết bị đầu cuối.

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