Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux
Fatmawati Achmad Zaenuri / Shutterstock.com

ls > capture.txt
9,
cat capture.txt
0, và
cat capture.txt
1 là ba luồng dữ liệu được tạo khi bạn khởi chạy một lệnh Linux. Bạn có thể sử dụng chúng để biết liệu các tập lệnh của bạn đang được chuyển hướng hoặc chuyển hướng. Chúng tôi chỉ cho bạn cách làm.

Luồng tham gia hai điểm

Ngay khi bạn bắt đầu tìm hiểu về các hệ điều hành giống như Linux và Unix, bạn sẽ bắt gặp các thuật ngữ

ls > capture.txt
9,
cat capture.txt
0, và
cat capture.txt
4. Đây là ba luồng tiêu chuẩn được thiết lập khi một lệnh Linux được thực thi. Trong máy tính, luồng là thứ có thể truyền dữ liệu. Trong trường hợp của các luồng này, dữ liệu đó là văn bản.

Các dòng dữ liệu, giống như dòng nước, có hai đầu. Chúng có một nguồn và một luồng ra. Bất kỳ lệnh Linux nào bạn đang sử dụng đều cung cấp một đầu của mỗi luồng. Đầu kia được xác định bởi trình bao khởi chạy lệnh. Đầu cuối đó sẽ được kết nối với cửa sổ đầu cuối, được kết nối với đường ống hoặc được chuyển hướng đến tệp hoặc lệnh khác, theo dòng lệnh đã khởi chạy lệnh.

Luồng chuẩn Linux

Trong Linux,

ls > capture.txt
9 là dòng đầu vào tiêu chuẩn. Điều này chấp nhận văn bản làm đầu vào của nó. Đầu ra văn bản từ lệnh tới trình bao được gửi qua
cat capture.txt
0 (tiêu chuẩn ra) luồng. Thông báo lỗi từ lệnh được gửi qua
cat capture.txt
1 (lỗi tiêu chuẩn) luồng.

Vì vậy, bạn có thể thấy rằng có hai luồng đầu ra,

cat capture.txt
0 và
cat capture.txt
1và một luồng đầu vào,
ls > capture.txt
9. Bởi vì các thông báo lỗi và đầu ra bình thường đều có ống dẫn riêng để đưa chúng đến cửa sổ đầu cuối, chúng có thể được xử lý độc lập với nhau.

Luồng được xử lý giống như tệp

Các luồng trong Linux — giống như hầu hết mọi thứ khác — được coi như thể chúng là tệp. Bạn có thể đọc văn bản từ một tệp và bạn có thể ghi văn bản vào một tệp. Cả hai hành động này đều liên quan đến một luồng dữ liệu. Vì vậy, khái niệm xử lý một luồng dữ liệu dưới dạng tệp không quá phức tạp.

Mỗi tệp được liên kết với một quy trình được cấp phát một số duy nhất để xác định nó. Đây được gọi là bộ mô tả tệp. Bất cứ khi nào một hành động được yêu cầu thực hiện trên tệp, bộ mô tả tệp được sử dụng để xác định tệp.

Những giá trị này luôn được sử dụng cho

ls > capture.txt
9,
#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt
2 và
cat capture.txt
1:

  • 0: stdin
  • 1: stdout
  • 2: stderr

Phản ứng với Pipes và Redirects

Để dễ dàng giới thiệu một ai đó về một chủ đề, một kỹ thuật phổ biến là dạy một phiên bản đơn giản hóa của chủ đề. Ví dụ, với ngữ pháp, chúng ta được biết rằng quy tắc là “I trước E, ngoại trừ sau C.” Nhưng trên thực tế, có nhiều trường hợp ngoại lệ đối với quy tắc này hơn là có những trường hợp tuân theo nó.

Theo một cách tương tự, khi nói về

ls > capture.txt
9,
cat capture.txt
0, và
cat capture.txt
1 thật tiện lợi khi đưa ra tiên đề được chấp nhận mà một quá trình không biết cũng như không quan tâm đến nơi mà ba luồng tiêu chuẩn của nó được kết thúc. Một quy trình có nên quan tâm đến việc liệu đầu ra của nó đang đi đến thiết bị đầu cuối hay được chuyển hướng thành một tệp không? Nó thậm chí có thể biết liệu đầu vào của nó đến từ bàn phím hay đang được đưa vào nó từ một quá trình khác?

Trên thực tế, một quy trình biết — hoặc ít nhất là nó có thể tìm ra, nếu nó chọn kiểm tra — và nó có thể thay đổi hành vi của mình cho phù hợp nếu tác giả phần mềm quyết định thêm chức năng đó.

Chúng ta có thể thấy sự thay đổi hành vi này rất dễ dàng. Hãy thử hai lệnh sau:

ls

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

ls | cat

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Các

#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt
7 lệnh hoạt động khác nếu đầu ra của nó (
cat capture.txt
0) đang được đưa vào một lệnh khác. Nó là
#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt
7 chuyển sang một đầu ra cột duy nhất, nó không phải là chuyển đổi được thực hiện bởi
chmod +x error.sh
0. Và
#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt
7 thực hiện điều tương tự nếu đầu ra của nó đang được chuyển hướng:

ls > capture.txt

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

cat capture.txt

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Chuyển hướng stdout và stderr

Có một lợi thế khi có thông báo lỗi được gửi bởi một luồng chuyên dụng. Nó có nghĩa là chúng ta có thể chuyển hướng đầu ra của lệnh (

cat capture.txt
0) vào một tệp và vẫn thấy bất kỳ thông báo lỗi nào (
cat capture.txt
1) trong cửa sổ đầu cuối. Bạn có thể phản ứng với các lỗi nếu bạn cần, khi chúng xảy ra. Nó cũng ngăn các thông báo lỗi làm nhiễm bẩn tệp
cat capture.txt
0 đã được chuyển hướng vào.

Nhập văn bản sau vào một trình soạn thảo và lưu nó vào một tệp có tên là error.sh.

#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt

Làm cho tập lệnh có thể thực thi được bằng lệnh này:

chmod +x error.sh

Dòng đầu tiên của tập lệnh lặp lại văn bản tới cửa sổ đầu cuối, thông qua

cat capture.txt
0 suối. Dòng thứ hai cố gắng truy cập một tệp không tồn tại. Điều này sẽ tạo ra một thông báo lỗi được gửi qua
cat capture.txt
1.

Chạy tập lệnh bằng lệnh này:

./error.sh

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Chúng ta có thể thấy rằng cả hai luồng đầu ra,

cat capture.txt
0 và
cat capture.txt
1, đã được hiển thị trong các cửa sổ đầu cuối.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Hãy thử chuyển hướng đầu ra đến một tệp:

./error.sh > capture.txt

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Thông báo lỗi được gửi qua

cat capture.txt
1 vẫn được gửi đến cửa sổ đầu cuối. Chúng tôi có thể kiểm tra nội dung của tệp để xem liệu
cat capture.txt
0 đầu ra được chuyển đến tệp.

cat capture.txt

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Đầu ra từ

ls > capture.txt
9 đã được chuyển hướng đến tệp như mong đợi.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Các

./error.sh
2 biểu tượng chuyển hướng hoạt động với
cat capture.txt
0 theo mặc định. Bạn có thể sử dụng một trong các bộ mô tả tệp số để cho biết luồng đầu ra chuẩn nào bạn muốn chuyển hướng.

Để chuyển hướng rõ ràng

cat capture.txt
0, sử dụng hướng dẫn chuyển hướng này:

1>

Để chuyển hướng rõ ràng

cat capture.txt
1, sử dụng hướng dẫn chuyển hướng này:

ls | cat
0

Hãy thử kiểm tra lại và lần này chúng ta sẽ sử dụng

./error.sh
6:

ls | cat
1

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Thông báo lỗi được chuyển hướng và

cat capture.txt
0
./error.sh
8 tin nhắn được gửi đến cửa sổ đầu cuối:

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Hãy xem những gì có trong tệp capture.txt.

cat capture.txt

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Các

cat capture.txt
1 tin nhắn ở dạng capture.txt như mong đợi.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Chuyển hướng Cả stdout và stderr

Chắc chắn, nếu chúng ta có thể chuyển hướng

cat capture.txt
0 hoặc là
cat capture.txt
1 đến một tệp độc lập với nhau, chúng ta phải có thể chuyển hướng cả hai cùng một lúc, đến hai tệp khác nhau?

Có, chúng tôi có thể. Lệnh này sẽ hướng

cat capture.txt
0 vào một tệp có tên là capture.txt và
cat capture.txt
1 vào một tệp có tên là error.txt.

ls | cat
3

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Bởi vì cả hai luồng đầu ra – đầu ra tiêu chuẩn và lỗi tiêu chuẩn – đều được chuyển hướng đến tệp, không có đầu ra hiển thị trong cửa sổ đầu cuối. Chúng tôi được quay trở lại dấu nhắc dòng lệnh như thể không có gì xảy ra.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Hãy kiểm tra nội dung của từng tệp:

cat capture.txt
ls | cat
5

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Chuyển hướng stdout và stderr đến cùng một tệp

Thật gọn gàng, chúng tôi có từng luồng đầu ra tiêu chuẩn đi đến tệp chuyên dụng của riêng nó. Sự kết hợp duy nhất khác mà chúng tôi có thể làm là gửi cả hai

cat capture.txt
0 và
cat capture.txt
1 vào cùng một tệp.

Chúng ta có thể đạt được điều này bằng lệnh sau:

ls | cat
6

Hãy phá vỡ điều đó.

  • ./error.sh: Khởi chạy tệp kịch bản error.sh.
  • > capture.txt: Chuyển hướng
    cat capture.txt
    0 truyền tới tệp capture.txt.
    ./error.sh
    2 là viết tắt của
    ./error.sh > capture.txt
    8.
  • 2> & 1: Điều này sử dụng lệnh &> chuyển hướng. Hướng dẫn này cho phép bạn ra lệnh cho trình bao để làm cho một luồng đến cùng đích với một luồng khác. Trong trường hợp này, chúng tôi đang nói “chuyển hướng luồng 2,
    cat capture.txt
    1, đến cùng đích mà luồng 1,
    cat capture.txt
    0, đang được chuyển hướng đến. ”

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Không có đầu ra hiển thị. Điều đó thật đáng khích lệ.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Hãy kiểm tra tệp capture.txt và xem có gì trong đó.

cat capture.txt

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Cả hai

cat capture.txt
0 và
cat capture.txt
1 luồng đã được chuyển hướng đến một tệp đích duy nhất.

Để đầu ra của luồng được chuyển hướng và bị loại bỏ một cách âm thầm, hãy hướng đầu ra tới

cat capture.txt
3.

Phát hiện chuyển hướng trong tập lệnh

Chúng ta đã thảo luận về cách một lệnh có thể phát hiện xem có bất kỳ luồng nào đang được chuyển hướng hay không và có thể chọn thay đổi hành vi của nó cho phù hợp. Chúng ta có thể thực hiện điều này trong các tập lệnh của riêng mình không? Có, chúng tôi có thể. Và nó là một kỹ thuật rất dễ hiểu và sử dụng.

Nhập văn bản sau vào một trình soạn thảo và lưu nó dưới dạng input.sh.

ls | cat
8

Sử dụng lệnh sau để làm cho nó có thể thực thi được:

ls | cat
9

Phần thông minh là bài kiểm tra trong ngoặc vuông. Các

cat capture.txt
4 (terminal) tùy chọn trả về true (0) nếu tệp được liên kết với bộ mô tả tệp kết thúc trong cửa sổ đầu cuối. Chúng tôi đã sử dụng bộ mô tả tệp 0 làm đối số cho kiểm tra, đại diện cho
ls > capture.txt
9.

Nếu

ls > capture.txt
9 được kết nối với một cửa sổ đầu cuối, thử nghiệm sẽ chứng minh là đúng. Nếu
ls > capture.txt
9 được kết nối với một tệp hoặc một đường ống, quá trình kiểm tra sẽ không thành công.

Chúng tôi có thể sử dụng bất kỳ tệp văn bản thuận tiện nào để tạo đầu vào cho tập lệnh. Ở đây chúng tôi đang sử dụng một tệp có tên là dummy.txt.

ls > capture.txt
0

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Kết quả đầu ra cho thấy rằng tập lệnh nhận ra rằng đầu vào không đến từ bàn phím, nó đến từ một tệp. Nếu bạn đã chọn, bạn có thể thay đổi hành vi của tập lệnh của mình cho phù hợp.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Đó là với chuyển hướng tệp, hãy thử nó với một đường ống.

ls > capture.txt
1

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Tập lệnh nhận ra rằng đầu vào của nó đang được đưa vào nó. Hay chính xác hơn, nó nhận ra một lần nữa rằng

ls > capture.txt
9 luồng không được kết nối với cửa sổ đầu cuối.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Hãy chạy tập lệnh mà không có đường dẫn hoặc chuyển hướng.

ls > capture.txt
2

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Các

ls > capture.txt
9 luồng được kết nối với cửa sổ đầu cuối và tập lệnh báo cáo điều này tương ứng.

Để kiểm tra điều tương tự với luồng đầu ra, chúng ta cần một tập lệnh mới. Nhập nội dung sau vào một trình soạn thảo và lưu nó dưới dạng output.sh.

ls > capture.txt
3

Sử dụng lệnh sau để làm cho nó có thể thực thi được:

ls | cat
9

Phần thông minh là bài kiểm tra trong ngoặc vuông. Các

cat capture.txt
4 (terminal) tùy chọn trả về true (0) nếu tệp được liên kết với bộ mô tả tệp kết thúc trong cửa sổ đầu cuối. Chúng tôi đã sử dụng bộ mô tả tệp 0 làm đối số cho kiểm tra, đại diện cho
ls > capture.txt
9.

Hãy thử nó ra. Chúng tôi sẽ chuyển đầu ra thông qua

chmod +x error.sh
0.

ls > capture.txt
5

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Tập lệnh nhận ra rằng đầu ra của nó không trực tiếp đến cửa sổ đầu cuối.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Chúng tôi cũng có thể kiểm tra tập lệnh bằng cách chuyển hướng đầu ra thành một tệp.

ls > capture.txt
6

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Không có đầu ra cho cửa sổ đầu cuối, chúng tôi được đưa trở lại dấu nhắc lệnh một cách âm thầm. Như chúng tôi mong đợi.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Chúng ta có thể xem bên trong tệp capture.txt để xem những gì đã được chụp. Sử dụng lệnh sau để làm như vậy.

ls > capture.txt
7

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Một lần nữa, kiểm tra đơn giản trong tập lệnh của chúng tôi phát hiện ra rằng

cat capture.txt
0 luồng không được gửi trực tiếp đến cửa sổ đầu cuối.

Nếu chúng tôi chạy tập lệnh mà không có bất kỳ đường dẫn hoặc chuyển hướng nào, nó sẽ phát hiện ra rằng

cat capture.txt
0 đang được chuyển trực tiếp đến cửa sổ đầu cuối.

ls > capture.txt
8

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Và đó chính xác là những gì chúng ta thấy.

Hướng dẫn stdin stdout stderr trong linux - stdin stdout stderr trong linux

Dòng ý thức

Biết cách biết các tập lệnh của bạn có được kết nối với cửa sổ đầu cuối hay đường ống dẫn hoặc đang được chuyển hướng hay không, cho phép bạn điều chỉnh hành vi của chúng cho phù hợp.

Kết quả ghi nhật ký và chẩn đoán có thể chi tiết hơn hoặc ít hơn, tùy thuộc vào việc nó xuất hiện trên màn hình hay một tệp tin. Thông báo lỗi có thể được ghi vào một tệp khác với đầu ra chương trình bình thường.

Như thường lệ, nhiều kiến ​​thức hơn mang lại nhiều lựa chọn hơn.