玩轉Linux檔案描述符和重定向

2021-06-20 02:20:41 字數 4226 閱讀 4785

原文出處:

linux下的檔案描述符是與檔案輸入、輸出相關聯的整數。它們用來跟蹤已開啟的檔案。

最常見的檔案描述符是stdin、stdout和stderr.我們可以將某個檔案描述符的內容重定向到另乙個檔案描述符中。

下面給出一些對檔案描述符進行操作和重定向的例子。

1.5.1 預備知識

我們在編寫指令碼時會頻繁使用標準輸入(stdin)、標準輸出(stdout)和標準錯誤(stderr)。

通過內容過濾將輸出重定向到檔案是我們從事的基礎任務之一。

當命令輸出文字時,這些輸出文字有可能是錯誤資訊,也可能是正常的(非錯誤的)輸出資訊。

單靠檢視輸出的文字本身,  我們無法區分哪些是正常的輸出文字,哪些是錯誤文字。不過,我們可以通過檔案描述符來解決這個問題,將那些與特定描述符關聯的文字提取出來。

檔案描述符是與乙個開啟的檔案或資料流相關聯的整數。檔案描述符0、1以及2是系統預留的。

0——stdin(標準輸入)

1——stdout(標準輸出)

2——stderr(標準錯誤)

1.5.2  實戰演練

將輸出文字重定向或儲存到乙個檔案中:

$echo"this is a sample text 1">temp.txt

這種方法通過擷取檔案的方式,將輸出文字儲存到檔案temp.txt中,也就是說在把echo命令的輸出寫入檔案之前,temp.txt中的內容首先會被清空。

接下來,再看另乙個例子:

$echo "this is sample text 2" >>temp.txt

這種方法會將文字追加到目標檔案中。

>和》並不相同。儘管這兩個操作符都可以將文字重定向到檔案,但是前者會先清空檔案,再寫入內容;而後者會將內容追加到現有檔案的尾部。

可以用下面的方法檢視檔案內容:

$cat temp.txt

this is sample text 1

this is sample text 2

在linux作業系統中,當使用重定向操作符時,重定向的內容不會出現在終端,而是直接被匯入檔案。重定向操作符預設使用標準輸出。如果想使用特定的檔案描述符,你必須將描述符置於操作符之前。

>等同於1>;對於》來說,情況也類似(即》等同於1>>)。

來看看什麼是標準錯誤以及如何對它重定向。當命令輸出錯誤資訊時,stderr資訊就會被列印出來。考慮下面的例子:

$ is + 

is:cannot access +:no such file or directory 

這裡,+是乙個非法引數,因些將返回錯誤資訊。

[ 成功和不成功的命令

當乙個命令發生錯誤並退回時,它會返回乙個非0的退出狀態;而當命令成功完成後,它會返回數字0。退出狀態可以從特殊變數$? 中獲得(在命令執行語句之後立刻執行echo$?,就可以列印出退出狀態)。]

將stderr文字列印到螢幕上,而不是檔案中。

$ is+>out.txt

is:cannot access+:no such file or directory

然而在下面的命令中,stdout沒有任何輸出,因為錯誤已經重定向到out.txt中去了。

$ is +2> out.txt # 正常執行

你可以將stderr單獨重定向到乙個檔案,將stdout重定向到另乙個檔案:

$ cmd 2>stderr.txt 1>stdout.txt

還可以利用下面的方法將stderr轉換成stdout,使得stderr和stdout都被重定向到同乙個檔案中:

$ cmd 2>&1 output.txt

或者採用下列方法:

$ cmd&> output.txt

有時候,在輸出中可能包含一些不必要的資訊(比如除錯資訊)。如果你不想讓終端中充斥著有關stderr的繁枝末節,那麼你可以將stderr的輸出重定向到/dev/null, 保證一切都會被清除得乾乾淨淨。假設我們有三個檔案,分別是a1、a2、a3。但是普通使用者對a1沒有「讀一寫一執行」許可權。如果你需要列印檔案名以a起始的所有檔案的內容,你可以使用cat命令。

設定一些測試檔案:

$ echo a1 >a1

$ cp a1 a2;cp a2 a3;

$ chmod 000 a1 #清除所有許可權

儘管可以使用萬用字元(a*)顯示所有的檔案內容,但是系統會顯示乙個出錯資訊,因為對檔案a1沒有可讀許可權。

$ cat a* 

cat:a1 permission denied

a1

a1 

其中,cat:a1:permission denied 屬於stderr。我們可以將stderr資訊重定向到乙個檔案中,而stdout 仍然保持不變。考慮如下**:

$ cat a* 2>err.txt #stderr被重定向到err.txt

a1a1

$ cat err.txt

cat:a1:permission denied

觀察下面的**:

$ some_command 2>/dev/null

在這個示例中,來自stderr的輸出被丟到檔案/dev/null中。/dev/null是乙個特殊的裝置檔案,這個檔案接收到的任何資料都會被丟棄。

因此,null裝置通常也被為位桶(bit bucket)或黑洞。

當對stderr或stdout進行重定向時,重定向的文字將傳入檔案。

因為文字已經被重定向到檔案中,也就沒剩下什麼東西可以通過管道(|)傳給接下來的命令,而這些命令是通過stdin來接收文字的。

但是有乙個巧妙的方法可以一方面將資料重定向到檔案,另一方面還可以提供一些重定向資料的副本作為後續命令的stdin。

這一切都可以使用tee來實現。

舉個例子:要在終端中列印stdout,同時將它重定向到乙個檔案中,那麼可以這樣使用tee:

command | tee file1 file2 

在下面的**中,tee命令接收到來自stdin的資料。它將stdout的乙份副寫入檔案out.txt,同時將別乙份副本作為後續命令的stdin。命令cat -n將從stdin中接收到的每一行資料前加上行號並寫入stdout:

$ cat a*| tee out.txt| cat -n

cat: a1: permission denied

1 a1

2 a1  

檢視out.txt 的內容:

$ cat out.txt

a1a1 

注意,cat:a1:permission denied並沒有在任何檔案內容中出現。這是因為這些資訊屬於stderr,而tee只能從stdin中進行讀取。

預設情況下,tee命令會將檔案覆蓋,但是提供了乙個-a選項,可以用於追加內容。例如:

$ cat a*| tee -a out.txt| cat -n.

帶有引數的命令可以寫成:command file1 file2依次類推,或者簡簡單單地用command file。

我們可以使用stdin作為命令引數。只需要將-作為命令的檔名引數即可:

$ cmd1 |cmd2 |cmd - 

例如:$ echo who is this | tee-

who is this

who is this 

或者我們也可以將/dev/stdin作為輸出檔名來使用stdin。

類似的,使用/dev/stderr代表標準錯誤,/dev/stdout代表標準輸出。這些特殊的裝置檔案分別對應stdin、stderr和stdout。

補充內容:

從stdin讀取輸入的命令能以多種方式接收資料。另外,還可以用cat和管道來制定我們自己的檔案描述符,例如:

$ cat file | cmd

$ cmd1 | cmd2 

1.將檔案重定向到命令

借助重定向,我們可以像使用stdin那樣從檔案中讀取資料:

$ cmd

2.重定向指令碼內部的文字塊

有時候,需要對文字塊(多行文字)像標準輸入一樣進行重定向。考慮乙個特殊情況:源文字就位於shell指令碼中。

來看下面這段shell指令碼吧,向log檔案中寫入頭部資料,可以按照下面的方法完成:

#!/bin/bash

cat log file header

this is a test log file

function:system statistics

eof 

在cat $ cat log.txt

log file header

this is a test log file

function:system statistics

linux檔案描述符

本文介紹了檔案描述符,1 首先說什麼是檔案描述符,它有什麼作用?檔案描述符是乙個簡單的整數,用以標明每乙個被程序所開啟的檔案和socket。基於檔案描述符的輸入輸出函式 open 開啟乙個檔案,並指定訪問該檔案的方式,呼叫成功後返回乙個檔案描述符。creat 開啟乙個檔案,如果該檔案不存在,則建立它...

linux檔案描述符

當某個程式開啟檔案時,作業系統返回相應的檔案描述符,程式為了處理該檔案必須引用此描述符。所謂的檔案描述符是乙個低階的正整數。最前面的三個檔案描述符 0,1,2 分別與標準輸入 stdin 標準輸出 stdout 和標準錯誤 stderr 對應。因此,函式 scanf 使用 stdin,而函式 pri...

Linux 檔案描述符

我們之前就知道在linux作業系統下 一切皆檔案 所以在這個條件下,所有研究的物件都變相的相當於研究檔案,那麼對檔案系統的研究也應該是必須的。我們的核心利用檔案描述符來訪問檔案,每個檔案描述符都是非負整數,開啟現存的檔案或者是新建檔案時,核心會返回乙個檔案描述符,讀寫檔案也需要使用檔案描述符來指定待...