溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Bash中的&符號(hào)和文件描述符如何理解

發(fā)布時(shí)間:2022-01-07 16:07:58 來(lái)源:億速云 閱讀:184 作者:柒染 欄目:系統(tǒng)運(yùn)維

這篇文章將為大家詳細(xì)講解有關(guān)Bash中的&符號(hào)和文件描述符如何理解,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

在我們探究大多數(shù)鏈?zhǔn)?Bash 命令中出現(xiàn)的所有的雜項(xiàng)符號(hào)(&、|、;>、<、{[、()、]} 等等)的任務(wù)中,我們一直在仔細(xì)研究 & 符號(hào)。

上次,我們看到了如何使用 & 把可能需要很長(zhǎng)時(shí)間運(yùn)行的進(jìn)程放到后臺(tái)運(yùn)行。但是, 與尖括號(hào) < 結(jié)合使用,也可用于將輸出或輸出通過(guò)管道導(dǎo)向其他地方。

在 前面的 尖括號(hào)教程中,你看到了如何使用 >,如下:

ls > list.txt

ls 輸出傳遞給 list.txt 文件。

現(xiàn)在我們看到的是簡(jiǎn)寫(xiě):

ls 1> list.txt

在這種情況下,1 是一個(gè)文件描述符,指向標(biāo)準(zhǔn)輸出(stdout)。

以類(lèi)似的方式,2 指向標(biāo)準(zhǔn)錯(cuò)誤輸出(stderr):

ls 2> error.log

所有錯(cuò)誤消息都通過(guò)管道傳遞給 error.log 文件。

回顧一下:1> 是標(biāo)準(zhǔn)輸出(stdout),2> 是標(biāo)準(zhǔn)錯(cuò)誤輸出(stderr)。

第三個(gè)標(biāo)準(zhǔn)文件描述符,0< 是標(biāo)準(zhǔn)輸入(stdin)。你可以看到它是一個(gè)輸入,因?yàn)榧^(<)指向0,而對(duì)于 12,箭頭(>)是指向外部的。

標(biāo)準(zhǔn)文件描述符有什么用?

如果你在閱讀本系列以后,你已經(jīng)多次使用標(biāo)準(zhǔn)輸出(1>)的簡(jiǎn)寫(xiě)形式:>。

例如,當(dāng)(假如)你知道你的命令會(huì)拋出一個(gè)錯(cuò)誤時(shí),像 stderr2)這樣的東西也很方便,但是 Bash 告訴你的東西是沒(méi)有用的,你不需要看到它。如果要在 home/ 目錄中創(chuàng)建目錄,例如:

mkdir newdir

如果 newdir/ 已經(jīng)存在,mkdir 將顯示錯(cuò)誤。但你為什么要關(guān)心這些呢?(好吧,在某些情況下你可能會(huì)關(guān)心,但并非總是如此。)在一天結(jié)束時(shí),newdir 會(huì)以某種方式讓你填入一些東西。你可以通過(guò)將錯(cuò)誤消息推入虛空(即 `/dev/null)來(lái)抑制錯(cuò)誤消息:

mkdir newdir 2> /dev/null

這不僅僅是 “讓我們不要看到丑陋和無(wú)關(guān)的錯(cuò)誤消息,因?yàn)樗鼈兒軣┤恕?,因?yàn)樵谀承┣闆r下,錯(cuò)誤消息可能會(huì)在其他地方引起一連串錯(cuò)誤。比如說(shuō),你想找到 /etc 下所有的 .service 文件。你可以這樣做:

find /etc -iname "*.service"

但事實(shí)證明,在大多數(shù)系統(tǒng)中,find 顯示的錯(cuò)誤會(huì)有許多行,因?yàn)槠胀ㄓ脩?hù)對(duì) /etc 下的某些文件夾沒(méi)有讀取訪(fǎng)問(wèn)權(quán)限。它使讀取正確的輸出變得很麻煩,如果 find 是更大的腳本的一部分,它可能會(huì)導(dǎo)致行中的下一個(gè)命令排隊(duì)。

相反,你可以這樣做:

find /etc -iname "*.service" 2> /dev/null

而且你只得到你想要的結(jié)果。

文件描述符入門(mén)

單獨(dú)的文件描述符 stdoutstderr 還有一些注意事項(xiàng)。如果要將輸出存儲(chǔ)在文件中,請(qǐng)執(zhí)行以下操作:

find /etc -iname "*.service" 1> services.txt

工作正常,因?yàn)?1> 意味著 “發(fā)送標(biāo)準(zhǔn)輸出且自身標(biāo)準(zhǔn)輸出(非標(biāo)準(zhǔn)錯(cuò)誤)到某個(gè)地方”。

但這里存在一個(gè)問(wèn)題:如果你想把命令拋出的錯(cuò)誤信息記錄到文件,而結(jié)果中沒(méi)有錯(cuò)誤信息你該怎么?上面的命令并不會(huì)這樣做,因?yàn)樗粚?xiě)入 find 正確的結(jié)果,而:

find /etc -iname "*.service" 2> services.txt

只會(huì)寫(xiě)入命令拋出的錯(cuò)誤信息。

我們?nèi)绾蔚玫絻烧撸空?qǐng)嘗試以下命令:

find /etc -iname "*.service" &> services.txt

&hellip;&hellip; 再次和 & 打個(gè)招呼!

我們一直在說(shuō) stdin0)、stdout1)和 stderr2)是“文件描述符”。文件描述符是一種特殊構(gòu)造,是指向文件的通道,用于讀取或?qū)懭耄騼烧呒娑兄?。這來(lái)自于將所有內(nèi)容都視為文件的舊  UNIX 理念。想寫(xiě)一個(gè)設(shè)備?將其視為文件。想寫(xiě)入套接字并通過(guò)網(wǎng)絡(luò)發(fā)送數(shù)據(jù)?將其視為文件。想要讀取和寫(xiě)入文件?嗯,顯然,將其視為文件。

因此,在管理命令的輸出和錯(cuò)誤的位置時(shí),將目標(biāo)視為文件。因此,當(dāng)你打開(kāi)它們來(lái)讀取和寫(xiě)入它們時(shí),它們都會(huì)獲得文件描述符。

這是一個(gè)有趣的效果。例如,你可以將內(nèi)容從一個(gè)文件描述符傳遞到另一個(gè)文件描述符:

find /etc -iname "*.service" 1> services.txt 2>&1

這會(huì)將 stderr 導(dǎo)向到 stdout,而 stdout 通過(guò)管道被導(dǎo)向到一個(gè)文件中 services.txt 中。

它再次出現(xiàn):& 發(fā)信號(hào)通知 Bash 1 是目標(biāo)文件描述符。

標(biāo)準(zhǔn)文件描述符的另一個(gè)問(wèn)題是,當(dāng)你從一個(gè)管道傳輸?shù)搅硪粋€(gè)時(shí),你執(zhí)行此操作的順序有點(diǎn)違反直覺(jué)。例如,按照上面的命令。它看起來(lái)像是錯(cuò)誤的方式。你也行像這樣閱讀它:“將輸出導(dǎo)向到文件,然后將錯(cuò)誤導(dǎo)向到標(biāo)準(zhǔn)輸出?!?看起來(lái)錯(cuò)誤輸出會(huì)在后面,并且在輸出到標(biāo)準(zhǔn)輸出(1)已經(jīng)完成時(shí)才發(fā)送。

但這不是文件描述符的工作方式。文件描述符不是文件的占位符,而是文件的輸入和(或)輸出通道。在這種情況下,當(dāng)你做 1> services.txt 時(shí),你的意思是 “打開(kāi)一個(gè)寫(xiě)管道到 services.txt 并保持打開(kāi)狀態(tài)”。1 是你要使用的管道的名稱(chēng),它將保持打開(kāi)狀態(tài)直到該行的結(jié)尾。

如果你仍然認(rèn)為這是錯(cuò)誤的方法,試試這個(gè):

find /etc -iname "*.service" 2>&1 1>services.txt

并注意它是如何不工作的;注意錯(cuò)誤是如何被導(dǎo)向到終端的,而只有非錯(cuò)誤的輸出(即 stdout)被推送到 services.txt

這是因?yàn)?Bash 從左到右處理 find 的每個(gè)結(jié)果。這樣想:當(dāng) Bash 到達(dá) 2>&1 時(shí),stdout1)仍然是指向終端的通道。如果 find 給 Bash 的結(jié)果包含一個(gè)錯(cuò)誤,它將被彈出到 2,轉(zhuǎn)移到 1,然后留在終端!

然后在命令結(jié)束時(shí),Bash 看到你要打開(kāi) stdout1) 作為到 services.txt 文件的通道。如果沒(méi)有發(fā)生錯(cuò)誤,結(jié)果將通過(guò)通道 1 進(jìn)入文件。

相比之下,在:

find /etc -iname "*.service" 1>services.txt 2>&1

1 從一開(kāi)始就指向 services.txt,因此任何彈出到 2 的內(nèi)容都會(huì)導(dǎo)向到 1 ,而 1 已經(jīng)指向最終去的位置 services.txt,這就是它工作的原因。

在任何情況下,如上所述 &> 都是“標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤”的縮寫(xiě),即 2>&1。

這可能有點(diǎn)多,但不用擔(dān)心。重新導(dǎo)向文件描述符在 Bash 命令行和腳本中是司空見(jiàn)慣的事。

關(guān)于Bash中的&符號(hào)和文件描述符如何理解就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI