2013-02-04 40 views
7

Tôi muốn chạy đầu ra của chương trình thông qua một đường ống, nhưng nó dường như hoạt động khác nhau khi nó phát hiện stdout không phải là một trình bao tương tác.Bash: lừa chương trình vào suy nghĩ stdout là một thiết bị đầu cuối tương tác

Làm cách nào tôi có thể đánh lừa nó bằng văn bản thông qua đường ống giống như trong hoàn cảnh thông thường?

+1

Tôi đã nghe ' expect' là một chương trình tốt để làm điều đó – BeniBela

+0

Cũng kiểm tra chương trình 'script' cho mục đích đó: http://stackoverflow.com/a/1402389/516188 –

Trả lời

12

Tôi giả định rằng chương trình sẽ gọi hàm glibc isatty() để kiểm tra xem stdout có phải là thiết bị đầu cuối hay không. Đó là điều phổ biến đối với các chương trình sử dụng đầu ra được tô màu trên các đầu cuối hoặc các tính năng khác của thiết bị đầu cuối ANSI như định vị con trỏ hoặc xóa/vẽ lại đường.

Bạn có thể đánh lừa chương trình bằng biến môi trường LD_PRELOAD. LD_PRELOAD được liên kết ELF xử lý và cho biết rằng thư viện động phải được tải trước tất cả những thứ khác. Sử dụng tính năng này, bạn có thể ghi đè các hàm thư viện, trong trường hợp của bạn là hàm glibc isatty(). Bạn có thể làm theo ví dụ này article.

tôi đã chuẩn bị một ví dụ cho bạn:

Đầu tiên tạo ra các tập tin libisatty.c:

/** 
* Overrides the glibc function. Will always return true. 
* 
* Note: Although this should be ok for most applications it can 
* lead to unwanted side effects. It depends on the question 
* why the programm calls isatty() 
*/ 
int isatty(int param) { 
    return 1; 
} 

và biên dịch nó như là một lib chia sẻ:

gcc -shared -o libisatty.so libisatty.c 

Nó nên xây dựng tốt.

Bây giờ là lúc để kiểm tra thư viện. :) Tôi đã sử dụng lệnh ls --color=auto để kiểm tra. ls gọi isatty() để quyết định xem có nên tô màu đầu ra của nó hay không. Nếu đầu ra được chuyển hướng đến một tập tin hoặc một đường ống thì nó sẽ không được tô màu. Bạn có thể kiểm tra điều này một cách dễ dàng bằng cách sử dụng lệnh sau:

ls --color=auto  # should give you colorized output 
ls --color=auto | cat # will give you monochrome output 

Bây giờ chúng ta sẽ cố gắng lệnh thứ hai một lần nữa bằng cách sử dụng var môi trường LD_PRELOAD:

LD_PRELOAD=./libisatty.so ls --color=auto | cat 

Bạn sẽ thấy đầu ra colorized.

usename btw mát: uʍop ǝpısdn !!: D

+1

Chỉ ... wow! Câu trả lời tuyệt vời! – slezica

+0

Cảnh báo: việc tạo một hàm hệ vỏ thực hiện thủ thuật 'LD_PRELOAD' này không hoàn toàn hoạt động, vì dường như những thứ khác là những khác biệt quan sát được trong hàm vỏ (tôi không chắc chúng là gì). Tuy nhiên, tạo bí danh 'trick_tty' với' alias trick_tty = "LD_PRELOAD = <đường dẫn đầy đủ đến> /libisatty.so" 'và sau đó thực hiện' trick_tty | ít hoạt động hơn. – ntc2

+1

Đối với người dùng MacOS, bạn có thể làm tương tự nhưng thay vì đặt LD_PRELOAD, bạn đặt DYLD_INSERT_LIBRARIES và DYLD_FORCE_FLAT_NAMESPACE, như sau: 'DYLD_INSERT_LIBRARIES =./Libisatty.so DYLD_FORCE_FLAT_NAMESPACE = y ls -G | cat' (lưu ý - cờ màu không hoạt động trên ls của mac) –

0

Bạn có thể muốn thử điều này:

./script.sh < `tty` > output 

Nếu chương trình đang làm một cái gì đó giống như isatty(0), điều này có thể là đủ.

+3

Lưu ý rằng programm trong questio n sẽ chạy isatty() trên stdout. Bạn đường ống thiết bị đầu cuối để stdin.Điều này sẽ không giải quyết được vấn đề – hek2mgl

+0

Nó thực sự có thể được thử nghiệm stdin và không stdout – arnaud576875

+1

Điều này không có ý nghĩa. – hek2mgl

2

Sử dụng script công trình cho tôi:

script outputfile.txt yourcommand 
# any output ends up in outputfile.txt 

Bạn có thể sử dụng để ống Tôi đoán:

script out.txt yourcommand ; cat out.txt | nextcommand 
+0

Kiểm tra mã nguồn của 'script' sẽ tiết lộ những thứ khác, ngoài' isatty', được các chương trình sử dụng để biết chúng có đang chạy tương tác hay không. – ntc2

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