Các toán tử chuyển hướng luôn luôn mở mô tả tệp song song?


7

1. Xem xét đoạn trích số 1:

$ cat test.txt > test.txt
cat: test.txt: input file is output file

Dường như điều đó catlàm cho bộ mô tả tệp đầu vào của nó trỏ đến test.txt và sau đó khi nó cố gắng đặt bộ mô tả tệp đầu ra của nó thành test.txt, nó sẽ ném lỗi trên. Ở đây có vẻ như catbiết về toán tử chuyển hướng và vì vậy tiến hành thử đặt bộ mô tả tệp đầu ra thành test.txt

2. Xem xét đoạn trích số 2:

$ cat 1.txt
1:CAT
2:dog
$ sed 's/cat/CAT/g' test.txt
1:CAT
2:dog
$ sed 's/cat/CAT/g' test.txt > test.txt
$ cat test.txt # Note that test.txt is now empty
$

Ở đây chúng ta thấy rằng sedmở test.txt (đối số cuối cùng) trong chế độ đọc và đồng thời đặt test.txtlàm mô tả đầu ra tệp của nó. Ngoài ra, '>'toán tử ghi đè lên nội dung của tệp TRƯỚC KHI sedbắt đầu đọc từ nó.

Tôi biết rằng các lệnh trong một đường ống thực thi song song nhưng không bắt gặp bất kỳ thông tin nào về cách các toán tử chuyển hướng hành xử. Bất kỳ liên kết hỗ trợ sẽ hữu ích.


Câu trả lời:


11

Ngoài các tài liệu mà jordanm chỉ ra, tôi muốn đảm bảo sửa một quan niệm sai lầm được minh họa trong câu hỏi của bạn. Chương trình thực thi không xử lý các chuyển hướng. Nó hầu như không nhận thức được chúng. Vỏ xử lý chuyển hướng.

Một chương trình được bắt đầu với ba tệp được mở: stdin (# 0), stdout (# 1) và stderr (# 2). Nếu bạn chỉ chạy một chương trình từ dấu nhắc shell của mình, chúng sẽ được kết nối với thiết bị đầu cuối của bạn, vì vậy chương trình sẽ đọc những gì bạn nhập (stdin) và in đầu ra (stdout) và lỗi (stderr) đến thiết bị đầu cuối của bạn.

Ví dụ, tôi chỉ chạy cattrong một thiết bị đầu cuối (có nghĩa tty/dev/pts/31). Tôi có thể kiểm tra tập tin nào đã mở bằng lsof:

$ lsof -a -p `pidof cat` -d0,1,2
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
cat     21257 anthony    0u   CHR 136,31      0t0   34 /dev/pts/31
cat     21257 anthony    1u   CHR 136,31      0t0   34 /dev/pts/31
cat     21257 anthony    2u   CHR 136,31      0t0   34 /dev/pts/31

Thật vậy, chúng ta có thể thấy rằng nó có thiết bị đầu cuối mở cho cả ba. Bây giờ, thay vào đó, chúng ta hãy thử một lời mời mèo khá ngớ ngẩn : cat < /dev/zero > /dev/null 2>/dev/full, đó là chuyển hướng cả ba:

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
cat     21838 anthony    0r   CHR    1,5      0t0 1030 /dev/zero
cat     21838 anthony    1w   CHR    1,3      0t0 1028 /dev/null
cat     21838 anthony    2w   CHR    1,7      0t0 1031 /dev/full

Shell đã thực hiện các chuyển hướng đó bằng cách chuyển ba thiết bị là stdin, stdout và stderr (thay vì terminal). Vỏ tương tự thực hiện các đường ống. Hãy thử cat | dd > /dev/null(một đường ống khá ngớ ngẩn, thực sự):

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     22507 anthony    0u   CHR 136,31      0t0       34 /dev/pts/31
cat     22507 anthony    1w  FIFO    0,8      0t0 56081395 pipe
cat     22507 anthony    2u   CHR 136,31      0t0       34 /dev/pts/31

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
dd      22508 anthony    0r  FIFO    0,8      0t0 56081395 pipe
dd      22508 anthony    1u   CHR 136,31      0t0       34 /dev/null
dd      22508 anthony    2u   CHR 136,31      0t0       34 /dev/pts/31

Lưu ý cách shell đã mở một đường ống và nó đã sử dụng nó để kết nối thiết bị xuất chuẩn của catstdin của dd. Và hơn nữa làm thế nào nó đã kết nối ddthiết bị xuất chuẩn /dev/null.

Các lệnh đang chạy không thực sự nhận thức được các chuyển hướng. Họ chỉ sử dụng stdin, stdout, stderr như bình thường. Tất cả đều có thể là thiết bị đầu cuối hoặc chúng có thể được chuyển hướng đến / từ một tệp, thiết bị hoặc có thể là một đường ống đến một chương trình khác. Hoặc thậm chí là một ổ cắm mạng, nếu vỏ của bạn hỗ trợ điều đó.

Ngay cả các đường ống phức tạp nhất cũng thực sự chỉ là các hướng dẫn cho trình bao về cách kết nối ba tay cầm tệp đó trước khi thực hiện chương trình.

(Chú ý: Một số chương trình hành xử khác nhau trong trường hợp một trong những được gắn vào một thiết bị đầu cuối, nhưng đó là bình thường để có nhiều người dùng thân thiện trong sử dụng tương tác Ví dụ, lschuyển sang đầu ra duy nhất cột và không có màu sắc khi thiết bị xuất chuẩn không phải là một Thiết bị đầu cuối thường là thứ bạn muốn nếu bạn sắp chuyển nó sang chương trình khác. Một số chương trình xử lý nhắc nhở khác nhau nếu stdin không phải là thiết bị đầu cuối. V.v.)


Cảm ơn bạn @derobert! Đó là một lời giải thích tuyệt vời. Tôi đã nhìn xung quanh nếu có một cách để kiểm tra cách thức cathoạt động đằng sau hậu trường, và rất may bạn đã minh họa điều đó.
Kent Pawar

10

Chuyển hướng xảy ra đầu tiên trong vỏ. Trong ví dụ của bạn:

cat test.txt > test.txt

Điều đầu tiên xảy ra là bash mở ra test.txt, nó cắt bớt tệp. Bây giờ nó trống, trước khi catđược thực hiện với test.txttư cách là một đối số.

Từ phần chuyển hướng của trang bash:

Trước khi một lệnh được thực thi, đầu vào và đầu ra của nó có thể được chuyển hướng bằng cách sử dụng một ký hiệu đặc biệt được giải thích bởi shell. Chuyển hướng cũng có thể được sử dụng để mở và đóng tệp cho môi trường thực thi shell hiện tại. Các toán tử chuyển hướng sau có thể đi trước hoặc xuất hiện ở bất kỳ đâu trong một lệnh đơn giản hoặc có thể theo lệnh. Chuyển hướng được xử lý theo thứ tự chúng xuất hiện, từ trái sang phải.

Tôi không thấy bất cứ điều gì trong đặc tả POSIX để chỉ ra rằng nó sẽ xảy ra trước tiên, nhưng tôi không biết về một vỏ mà nó không có.

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.