Ưu tiên của stdin và chuyển hướng xuất sắc trong Bash


9

Câu hỏi của tôi là về ưu tiên chuyển hướng là bash. Giả sử bạn có một lệnh:

cmd1 < cmd2 > cmd3

Nó sẽ dịch sang:

(cmd1 < cmd2) > cmd3

Hoặc là

cmd1 < (cmd2 > cmd3)

Câu trả lời:


11

Các quy định cụ thể tiêu chuẩn POSIX rằng chuyển hướng vỏ được từ trái sang phải; đó là, trật tự là rất quan trọng:

Cấu trúc 2>&1thường được sử dụng để chuyển hướng lỗi tiêu chuẩn sang cùng một tệp với đầu ra tiêu chuẩn. Vì các chuyển hướng diễn ra từ đầu đến cuối, thứ tự chuyển hướng là rất quan trọng. Ví dụ:

ls > foo 2>&1

chỉ đạo cả đầu ra tiêu chuẩn và lỗi tiêu chuẩn vào tập tin foo. Tuy nhiên:

ls 2>&1 > foo

chỉ hướng đầu ra tiêu chuẩn vào tập tin foovì lỗi tiêu chuẩn được nhân đôi thành đầu ra tiêu chuẩn trước khi đầu ra tiêu chuẩn được chuyển đến tập tin foo.

bash hoạt động tuân thủ phần này của tiêu chuẩn:

$ ls doesnotexist > foo 2>&1
$ cat foo
ls: cannot access doesnotexist: No such file or directory
$ ls doesnotexist 2>&1 > foo
ls: cannot access doesnotexist: No such file or directory
$ cat foo
$ 

Đối với đường ống:

Bởi vì việc gán đường ống của đầu vào tiêu chuẩn hoặc đầu ra tiêu chuẩn hoặc cả hai diễn ra trước khi chuyển hướng, nó có thể được sửa đổi bằng cách chuyển hướng. Ví dụ:

$ command1 2>&1 | command2

gửi cả đầu ra tiêu chuẩn và lỗi command1tiêu chuẩn của đầu vào tiêu chuẩn của command2.


Điều đó giả định rằng vỏ Bash là POSIX-tuân thủ.
fpmurphy

1
Tôi không nhận được nó. Vì bạn đã nói thứ tự là từ trái sang phải, không nên ls > foo 2>&1có nghĩa là chuyển hướng thiết bị xuất chuẩn sang foo sau đó chuyển hướng thiết bị xuất chuẩn sang thiết bị xuất chuẩn. Vì vậy, điều này không nên làm việc. Tương tự lệnh thứ hai sẽ hoạt động. Tôi đang thiếu gì ở đây?
Deepak Găngal

1
@fpmurphy bashnói chung là tuân thủ POSIX, ngoại trừ trong các tình huống được nêu ở đây , nơi bashhành vi mặc định khác nhau. Để làm cho bashphù hợp hơn, bạn có thể sử dụng --posixtùy chọn.
Matt Eckert

@dpacmittal Ví dụ đầu tiên ls > foo 2>&1, hoạt động như thế này: đầu tiên, đầu ra tiêu chuẩn được chuyển hướng đến foo, sau đó, lỗi tiêu chuẩn được chuyển hướng đến đầu ra tiêu chuẩn, hiện là tệp foo. Ví dụ thứ hai ls 2>&1 > foo, hoạt động như thế này: lỗi tiêu chuẩn được chuyển hướng đến đầu ra tiêu chuẩn trước khi đầu ra tiêu chuẩn được chuyển hướng đến foo, do đó, lỗi tiêu chuẩn được lặp lại cục bộ thay vì được dẫn đến tệp.
Matt Eckert

4
@dpacmittal .. ls 2>&1 >foo có lẽ bạn có thể nghĩ về nó như thế này. stderr từ 'ls' được chuyển hướng đến thiết bị xuất chuẩn. Điều này sẽ xảy ra! Nó sẽ đi đến nơi mà thiết bị xuất chuẩn hiện đang được chỉ định để đi, bất kể bất kỳ chỉ thị nào khác liên quan đến thiết bị xuất chuẩn .. (vì đây là chỉ thị chính / đầu tiên của nó ) .. Sau đó, đến một chỉ thị khác nói rằng thiết bị xuất chuẩn sẽ chuyển đến "foo", và nó ... Hãy nhớ rằng: stderr không được chuyển thành thực sự trở thành thiết bị xuất chuẩn .. Nó chỉ đi đến nơi thiết bị xuất chuẩn được chỉ định tại thời điểm chỉ thị. (ví dụ: thiết bị đầu cuối)
Peter.O

4

Tôi đoán cũng không. Một cặp dấu ngoặc có nghĩa là một vỏ phụ. Nhưng trong trường hợp này, không có vỏ phụ sẽ được bắt đầu vì chuyển hướng. Bash chỉ đơn giản là ăn cmd2vào stdin và ăn stdout vào cmd3.

Tôi đang suy nghĩ, bạn có ý gì đó như thế cmd1 | cmd2 | cmd3nào? Bởi vì cmd2cmd3thường là các tệp bình thường thay vì "cmds".

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.