Một chương trình tiếp theo trong một đường ống có thể xem mã thoát của chương trình trước không?


8

Tôi muốn tạo ra một chuỗi các kịch bản Bash như thế này

prog1 | prog2

sao cho prog2 có thể thấy mã thoát của prog1 và hành động khác nhau dựa trên thông tin đó.

Điều này có thể không?


Bạn có thể xây dựng các hành động khác nhau một phần của câu hỏi của bạn?
devnull

Bạn có quyền kiểm soát hạn chế về khoảng cách prog2đã tiến triển khi prog1thoát ra ngoài, do bộ đệm bên trong được sử dụng để thực hiện đường ống và cách thức prog1prog2được lên lịch.
chepner

Đồng thời xem [Các lệnh đường ống chạy theo thứ tự nào?] (Unix.stackexchange.com/q/37508)
DK Bose

Câu trả lời:


4

Câu trả lời chung là không. Bạn có thể prog2thoát ra trước prog1cả khi bắt đầu (rõ ràng điều đó không thể xảy ra nếu prog2thực sự đọc một số thông tin đầu vào, điều mà bạn mong đợi nó sẽ làm nếu bạn đang sử dụng nó trong một đường ống). Nó chắc chắn có thể prog2thoát ra trước đó prog1; điều này xảy ra ví dụ khi prog2một chương trình tìm kiếm thoát ngay khi tìm thấy kết quả khớp, trong trường hợp đó prog1có thể chưa hoàn thành việc tạo ra tất cả dữ liệu.

Không có cách trực tiếp prog2để lấy trạng thái thoát prog1hoặc thậm chí để biết rằng prog1đã thoát. Tất cả những gì prog2có thể biết là prog1đã đóng đầu ống của nó, điều mà nó có thể làm mà không chết.

Nếu bạn muốn có được trạng thái thoát prog1khỏi prog2, có hai phương thức phổ biến: bạn có thể ghi nó vào một tệp hoặc bạn có thể gửi nó qua đường ống. Gửi trạng thái đầu ra là dòng cuối cùng của dữ liệu đường ống là một khả năng. Bạn phải đảm bảo không xử lý dòng cuối cùng cho đến khi bạn biết rằng đó là dòng cuối cùng, tức là cho đến khi bạn cố đọc dòng tiếp theo.

{ prog1; echo $?; } | 

Dưới đây là một ví dụ trong đó phía bên phải là một bộ lọc văn bản tô màu cho mỗi dòng có chứa từ lỗi Lỗi lỗi màu đỏ. Nếu phía bên trái không thành công, phía bên phải thoát ra với cùng trạng thái.

{ prog1; echo $?; } | awk '
    NR != 1 {
        if (line ~ /[Ee][Rr][Rr][Oo][Rr]/) print "\033[31m" line "\033[0m";
        else print line;
    }
    {line = $0}
    END {exit($0)}
'

Tôi đã cố gắng { command; echo ${PIPESTATUS[@]}; } | sort | ...để trạng thái thoát xuất hiện đầu tiên trong luồng. Tất cả đều rất thú vị!

@ illuminÉ Điều đó sẽ chỉ hoạt động nếu ${PIPESTATUS[@]}được sắp xếp trước mọi thứ khác trong đầu ra của command. Nếu commandin ra một loạt các số hoặc nếu nó có thể in ra văn bản tùy ý, bạn sẽ gặp rắc rối: bạn sẽ không thể phân biệt đầu ra của nó với dòng trạng thái.
Gilles 'SO- ngừng trở thành ác quỷ'

Cảm ơn bạn, thực sự nó chỉ thành công trong việc sắp xếp trạng thái thành công lên hàng đầu nếu lệnh không chứa 0 trong đầu ra lol. Tgif / s.

2

Mặc dù bạn có thể trong một số trường hợp đặc biệt (xem các câu trả lời khác) bạn không thể trong mọi trường hợp. Một số chương trình lọc sẽ tiếp tục hoạt động, trong khi các chương trình khác sẽ giữ tất cả đầu ra, giải phóng nó trong một vụ nổ duy nhất và sau đó thoát.

Đối với một ví dụ về chương trình "cứ tiếp tục", grepmáy chủ sẽ như vậy tail -f /var/log/some_log_file. Sử dụng sorttrong một đường ống gây ra một "gian hàng", như sortsẽ thu thập đầu vào cho đến khi đường ống phía trước nó đóng lại. Sử dụng xargsthêm một sự phức tạp nữa: các chương trình được bắt đầu bởi xargs(nó có thể bắt đầu nhiều trường hợp) một phần của đường ống dẫn hay không?


-1 bởi vì bạn được nâng cấp để hợp lý hóa một câu trả lời không chính xác.
ctrl-alt-delor

@ giàu hả? Câu trả lời của Bruce là chính xác (mặc dù đoạn thứ hai hơi khó hiểu).
Gilles 'SO- ngừng trở nên xấu xa'

1

Câu trả lời: Không trực tiếp.

@terdon đã minh họa rằng mã thoát của lệnh trước đó trong đường ống phải được gửi dưới dạng tham số rõ ràng cho lệnh tiếp theo.

Hãy nhớ rằng đường ống chỉ đơn thuần là ánh xạ STDIN của lệnh trước sang STDIN của lệnh tiếp theo; mã thoát không được xuất ra STDOUT (hoặc STDERR).


1
-1 bởi vì bạn được trích dẫn để trích dẫn một câu trả lời không chính xác và không nói nhiều hơn nữa.
ctrl-alt-delor

@richard đủ công bằng ... Tôi nên kiểm tra lại ... đó là điều đã xảy ra nếu tôi buộc bản thân phải trả lời một câu hỏi khi rất mệt mỏi ...
pepoluan

1

Tất cả quá trình, trong đường ống, được bắt đầu trước khi thoát. Do đó, prog2có thể phải có được thông tin này sau khi nó bắt đầu, nó cũng sẽ phải ngừng xử lý cho đến khi prog1thoát ra, điều này có thể làm tắc nghẽn đường ống. Dường như có những vấn đề cơ bản trong việc làm những gì bạn yêu cầu, không phải là những hạn chế của hệ điều hành.

Bạn có thể cần phải xem xét một tệp tạm thời hoặc đặt kết quả vào một biến.

Ví dụ cho một lượng nhỏ dữ liệu, sử dụng một biến.

tmp=$(prog1)
if test "z$PIPESTATUS" == "z0"
then
   
else
   
fi

Có một khoảng trống trong lý luận của bạn. prog2được bắt đầu trước khi prog1hoàn thành nói chung, nhưng có thể có một cách để nó nhận trạng thái đầu ra từ prog1khi nó đang chạy.
Gilles 'SO- ngừng trở thành ác quỷ'

0

Để kết thúc câu trả lời của Gilles ,

(prog1; echo $? > /tmp/prog1.status) | prog2

là một cách tiếp cận.  prog2có thể

  • đọc đầu vào tiêu chuẩn đến cuối, rồi đọc /tmp/prog1.status, hoặc
  • kiểm tra sự tồn tại của /tmp/prog1.statusđịnh kỳ trong khi đọc đầu vào tiêu chuẩn.
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.