2008-09-26 28 views
10

Tôi có hai (UNIX) chương trình A và B đọc và ghi từ stdin/stdout.Kết nối đầu vào _and_output giữa hai lệnh trong shell/bash

Vấn đề đầu tiên của tôi là cách kết nối giá trị của A thành stdin của B giá trị trung bình của B thành stdin của A. I.e., giống như A | B nhưng một đường ống hai chiều. Tôi nghi ngờ tôi có thể giải quyết điều này bằng cách using exec to redirect nhưng tôi không thể làm cho nó hoạt động. Các chương trình tương tác nên một tệp tạm thời sẽ không hoạt động. Vấn đề thứ hai là tôi muốn lặp lại mỗi hướng và đường ống một bản sao thông qua một chương trình khai thác gỗ để stdout để tôi có thể nhìn thấy lưu lượng truy cập (dòng văn bản) đi qua giữa các chương trình. Quay lại đầu trang Ở đây tôi có thể nhận được đi với tee> (...) nếu tôi có thể giải quyết vấn đề đầu tiên.

Cả hai vấn đề này có vẻ như họ cần phải có các giải pháp nổi tiếng nhưng tôi không thể tìm thấy bất cứ điều gì.

Tôi thích giải pháp vỏ POSIX, hoặc ít nhất một thứ hoạt động trong bash trên cygwin.

Nhờ câu trả lời của bạn, tôi đã đưa ra giải pháp sau. Các lệnh A/B sử dụng nc để nghe hai cổng. Chương trình ghi nhật ký sử dụng sed (với -u để xử lý không bị chặn).

bash-3.2$ fifodir=$(mktemp -d) 
bash-3.2$ mkfifo "$fifodir/echoAtoB" 
bash-3.2$ mkfifo "$fifodir/echoBtoA" 
bash-3.2$ sed -u 's/^/A->B: /' "$fifodir/echoAtoB" & 
bash-3.2$ sed -u 's/^/B->A: /' "$fifodir/echoBtoA" & 
bash-3.2$ mkfifo "$fifodir/loopback" 
bash-3.2$ nc -l -p 47002 < "$fifodir/loopback" \ 
      | tee "$fifodir/echoAtoB" \ 
      | nc -l -p 47001 \ 
      | tee "$fifodir/echoBtoA" > "$fifodir/loopback" 

Điều này nghe để kết nối với cổng 47001 và 47002 và lặp lại tất cả lưu lượng truy cập đến đầu ra tiêu chuẩn.

Trong vỏ 2 làm:

bash-3.2$ nc localhost 47001 

Trong vỏ 3 làm:

bash-3.2$ nc localhost 47002 

Bây giờ dòng nhập vào trong vỏ 2 sẽ được ghi vào shell 3 và ngược lại và giao thông được ghi nhận vào shell 1 , giống như:

B->A: input to port 47001 
A->B: input to port 47002 

Ở trên đã được thử nghiệm trên Cygwin

Cập nhật: Tập lệnh ở trên ngừng hoạt động sau một vài ngày (!). Rõ ràng nó có thể bế tắc. Một số gợi ý trong câu trả lời có thể đáng tin cậy hơn.

Trả lời

5

Bạn có thể có thể nhận được ngay với ống tên:

mkfifo pipe 
gawk '$1' < pipe | gawk '$1' > pipe 
10

Làm thế nào về một đường ống được đặt tên?

# mkfifo foo 
# A < foo | B > foo 
# rm foo 

Đối với phần thứ hai, tôi tin rằng tee là câu trả lời đúng. Vì vậy, nó sẽ trở thành:

# A < foo | tee logfile | B > foo 
4

Bạn có thể sử dụng Expect.

Mong đợi là công cụ để tự động hóa các ứng dụng tương tác như telnet, ftp, passwd, fsck, rlogin, mẹo, v.v.

Bạn có thể sử dụng đoạn mã sau (lấy từ Khám phá Expect cuốn sách) như là một điểm khởi đầu - nó kết nối đầu ra của proc1 tới đầu vào của proc2 và ngược lại, như bạn yêu cầu:

#!/usr/bin/expect -f 
spawn proc1 
set proc1 $spawn_id 
spawn proc2 
interact -u $proc1 
0

Câu hỏi này tương tự như one Tôi đã hỏi trước đây. Các giải pháp được đề xuất bởi những người khác là sử dụng các đường ống có tên, nhưng tôi nghi ngờ bạn không có chúng trong Cygwin. Hiện tại tôi đang gắn bó với my own (attempt at a) solution, nhưng nó yêu cầu /dev/fd/0 mà bạn có thể cũng không có.

Mặc dù tôi không thực sự thích khía cạnh đường truyền-chuỗi-như-chuỗi của twinpipe (được đề cập bởi JeeBee (139495)), nó có thể là tùy chọn duy nhất của bạn trong Cygwin.

3

Tôi đã dành rất nhiều thời gian cho việc này, đã từ bỏ và cuối cùng quyết định sử dụng ksh (vỏ Korn), điều này cho phép điều này.

cmd1 |& cmd2 >&p <&p 

nơi |& là một (ống) nhà điều hành để bắt đầu một quá trình đồng và &p là mô tả tập tin đó đồng bộ quá trình.

2

Tôi đã gặp vấn đề này tại một thời điểm và tôi đã cùng nhau lập chương trình C đơn giản này.

#include <stdio.h> 
#include <unistd.h> 

#define PERROR_AND_DIE(_x_) {perror(_x_); _exit(1);} 

int main(int argc, char **argv) { 
    int fd0[2]; 
    int fd1[2]; 


    if (argc != 3) { 
     fprintf(stdout, "Usage %s: \"[command 1]\" \"[command 2]\"\n", argv[0]); 
     _exit(1); 
    } 

    if (pipe(fd0) || pipe(fd1)) PERROR_AND_DIE("pipe") 

    pid_t id = fork(); 
    if (id == -1) PERROR_AND_DIE("fork"); 

    if (id) { 
     if (-1 == close(0)) PERROR_AND_DIE("P1: close 0"); 
     if (-1 == dup2(fd0[0], 0)) PERROR_AND_DIE("P1: dup 0"); //Read my STDIN from this pipe 

     if (-1 == close(1)) PERROR_AND_DIE("P1: close 1"); 
     if (-1 == dup2(fd1[1], 1)) PERROR_AND_DIE("P1: dup 1"); //Write my STDOUT here 
     execl("/bin/sh", "/bin/sh", "-c", argv[1], NULL); 
     PERROR_AND_DIE("P1: exec") 
    } 

    if (-1 == close(0)) PERROR_AND_DIE("P2: close 0"); 
    if (-1 == dup2(fd1[0], 0)) PERROR_AND_DIE("P2: dup 0"); 

    if (-1 == close(1)) PERROR_AND_DIE("P2: close 1"); 
    if (-1 == dup2(fd0[1], 1)) PERROR_AND_DIE("P2: dup 1"); 


    execl("/bin/sh", "/bin/sh", "-c", argv[2], NULL); 
    PERROR_AND_DIE("P2: exec") 
} 
0

tôi muốn đề nghị "coproc":

#! /bin/bash 
# initiator needs argument 

if [ $# -gt 0 ]; then 
    a=$1 
    echo "Question $a" 
else 
    read a 
fi 

if [ $# -gt 0 ]; then 
    read a 
    echo "$a" >&2 
else 
    echo "Answer to $a is ..." 
fi 

exit 0 

Sau đó xem phần này:

$ coproc ./dialog 
$ ./dialog test < /dev/fd/${COPROC[0]} > /dev/fd/${COPROC[1]} 
Answer to Question test is ... 
Các vấn đề liên quan