Làm cách nào tôi có thể gửi đọc và ghi trên một bộ mô tả tệp đến các nơi khác nhau?


7

Tôi có một tệp thực thi Linux foođọc đầu vào từ fd 0 và ghi đầu ra vào fd 0 ( không phải fd 1). Điều này chỉ hoạt động tốt để sử dụng tương tác trong thiết bị đầu cuối.

Từ dòng lệnh shell, làm thế nào tôi có thể thực hiện chương trình này sao cho các lần đọc từ fd 0 đến từ một tệp, nhưng ghi vào fd 0 đi vào một tệp khác?

Điều tốt nhất tôi có thể đưa ra là $ goo input.txt output.txt | foonơi goomột số chương trình trợ giúp, nhưng tôi không biết về bất kỳ chương trình helper hiện có, và tôi thậm chí không biết nếu ống được thành lập bởi |là hai chiều.


1
Ống là đơn hướng. Cách duy nhất để làm điều này là thay thế FD 0 bằng một ổ cắm được kết nối với chương trình xử lý việc đọc / ghi. Bất cứ ai đã viết chương trình ghi vào FD 0 cần phải được tát một chút.
Patrick

Cảm ơn. foo <> /dev/tcp/localhost/1234trong một cửa sổ và trong một cửa sổ nc -l 1234 < input.txt > output.txtkhác dường như làm việc!
Jay

1
Một giải pháp khác là sử dụng LD_PRELOADthư viện để ghi đè write()để write()các cuộc gọi đến FD 0 được đổi thành FD 1.
Patrick

@Patrick, ý tưởng LD_PRELOAD rất thông minh. Giả sử nó có thể được sử dụng (foo không được liên kết tĩnh, không setuid hoặc setgid, v.v.) và giả sử rằng nó không thể được sửa ở cấp mã nguồn và được xây dựng lại, có vẻ như nó có thể là một thứ khá lâu dài giải pháp.
trời ơi

... trong đó nó có thể được thiết lập trong một kịch bản trình bao bọc, với việc foodi chuyển ra $PATHvà trình bao bọc thay thế nó, sẽ cho phép có một footrong $PATHđó hoạt động theo cách mà nó nên được viết ở vị trí đầu tiên.
trời ơi

Câu trả lời:


6

Với socat(phiên bản 2 trở lên):

socat 'system:cat input.txt & cat > output.txt,commtype=socketpair' \
      'system:foo,nofork'

Hoặc thậm chí tốt hơn:

socat 'CREATE:output.txt%OPEN:input.txt' 'system:foo,commtype=socketpair'

Chúng tôi đang sử dụng một socketpairhướng hai chiều (các đường ống không phải là hai chiều trên Linux). Một lựa chọn khác là sử dụng thiết bị đầu cuối giả (cả hai chiều) bằng cách sử dụng commtype=ptyở trên. Đó có thể là một cách tốt hơn nếu foomong muốn nói chuyện với một thiết bị đầu cuối.

Hoặc bạn thực hiện socketpaircách tiếp cận perlnhư:

perl -MSocket -e '
  socketpair(A, B, AF_UNIX, SOCK_STREAM, PF_UNSPEC);
  if (fork) {
    close A;
    if (fork) {
      open STDOUT, ">&B";
      exec("cat", "input.txt")
    }
    open STDIN, "<&B";
    open STDOUT, ">output.txt";
    exec("cat")
  }
  close B;
  open STDIN, "<&A";
  exec "foo"'

(ở đây là một bằng chứng nhanh về khái niệm, bạn có thể muốn thêm kiểm tra lỗi và làm cho nó hiệu quả hơn bằng cách không sử dụng nhiều quy trình đó và tránh thực thi cat).


với socat 1.7.2.3, cái đầu tiên mang lại cho tôi E parseopts(): unknown option "commtype"và cái thứ hai mang lại cho tôi E CREATE: wrong number of parameters (3 instead of 1).
Jay

@Jay, vâng, đã có một số lượng lớn các tính năng mới trong phiên bản 2. Những lệnh đó dựa vào một số trong số chúng.
Stéphane Chazelas
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.