Stdin, stdout và stderr trên Linux là gì?

stdin, stdout, và stderr 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ẽ gặp phải các thuật ngữ stdin, stdout, và stederr. Đâ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,stdin 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 stdout (tiêu chuẩn ra) luồng. Thông báo lỗi từ lệnh được gửi qua stderr (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, stdoutstderrvà một luồng đầu vào, stdin. 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ý luồng dữ liệu dưới dạng tệp không phải là quá nhiều.

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 stdin, stdout,stderr:

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

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

Để giảm bớt sự giới thiệu của 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 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ề stdin, stdout, và stderr 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 xem đầu ra của nó có đ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

ls | con mèo

Các ls lệnh hoạt động khác nếu đầu ra của nó (stdout) đang được đưa vào một lệnh khác. Nó làls 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 con mèo. Và ls 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

cat capture.txt

Chuyển hướng stdout và stderr

Có một lợi thế khi có thông báo lỗi được phân phối bởi một luồng chuyên dụng. Điều đó có nghĩa là chúng ta có thể chuyển hướng đầu ra của lệnh (stdout) vào một tệp và vẫn thấy bất kỳ thông báo lỗi nào (stderr) 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ây nhiễm sang tệp stdout đã đượ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 "Sắp thử truy cập tệp không tồn tại" 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 quastdout suối. Dòng thứ hai cố gắng truy cập vào 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 stderr.

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

./error.sh

Chúng ta có thể thấy rằng cả hai luồng đầu ra, stdoutstderr, đã được hiển thị trong các cửa sổ đầu cuối.

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

./error.sh> capture.txt

Thông báo lỗi được gửi qua stderr 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 stdout đầu ra được chuyển đến tệp.

cat capture.txt

Đầu ra từ stdin đã được chuyển hướng đến tệp như mong đợi.

Các > biểu tượng chuyển hướng hoạt động với stdout 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 stdout, sử dụng hướng dẫn chuyển hướng này:

1>

Để chuyển hướng rõ ràng stderr, sử dụng hướng dẫn chuyển hướng này:

2>

Hãy thử kiểm tra lại bài kiểm tra của chúng tôi và lần này chúng tôi sẽ sử dụng 2>:

./error.sh 2> capture.txt

Thông báo lỗi được chuyển hướng và stdouttiếng vọng lại tin nhắn được gửi đến cửa sổ đầu cuối:

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

cat capture.txt

Các stderr tin nhắn ở dạng capture.txt như mong đợi.

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

Chắc chắn, nếu chúng ta có thể chuyển hướng stdout hoặc là stderr đến một tệp độc lập với nhau, chúng ta phải có thể chuyển hướng cả hai tệp 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 stdout vào một tệp có tên là capture.txt và stderr vào một tệp có tên là error.txt.

./error.sh 1> capture.txt 2> error.txt

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ãy kiểm tra nội dung của từng tệp:

cat capture.txt
cat error.txt

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

Thật đơn giản, chúng tôi đã đưa từng luồng đầu ra tiêu chuẩn vào 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 stdoutstderr vào cùng một tệp.

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

./error.sh> capture.txt 2> & 1

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 stdout truyền đến tệp capture.txt. > là viết tắt của 1>.
  • 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, stderr, đến cùng đích mà luồng 1, stdout, đang được chuyển hướng đến. ”

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

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

cat capture.txt

Cả hai stdoutstderr 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 / dev / null.

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 kịch bản 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.

#! / bin / bash if [-t 0]; sau đó echo stdin đến từ bàn phím khác echo stdin đến từ một đường ống hoặc một tệp fi

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

chmod + x input.sh

Phần thông minh là bài kiểm tra trong ngoặc vuông. Các -t (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 bài kiểm tra, bộ mô tả này đại diện chostdin.

Nếu stdin đượ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 stdin đượ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.

./input.sh <dummy.txt

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 mà đến từ một tệp. Nếu đã chọn, bạn có thể thay đổi hành vi của tập lệnh cho phù hợp.

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

mèo dummy.txt | ./input.sh

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 stdin luồng không được kết nối với cửa sổ đầu cuối.

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

./input.sh

Các stdin 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 chỉnh sửa và lưu nó dưới dạng output.sh.

#! / bin / bash if [-t 1]; sau đó echo stdout sẽ chuyển đến cửa sổ đầu cuối khác echo stdout đang được chuyển hướng hoặc chuyển hướng fi

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

chmod + x input.sh

Thay đổi đáng kể duy nhất đối với tập lệnh này là trong bài kiểm tra trong dấu ngoặc vuông. Chúng tôi đang sử dụng chữ số 1 để đại diện cho trình mô tả tệp cho stdout.

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

./output | con mèo

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.

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.

./output.sh> capture.txt

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.

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.

cat capture.sh

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 stdout 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 stdout đang được chuyển trực tiếp đến cửa sổ đầu cuối.

./output.sh

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

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ể ít hoặc nhiều chi tiết hơn, tùy thuộc vào việc nó sẽ 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.


$config[zx-auto] not found$config[zx-overlay] not found