- Linux程序設(shè)計(jì)(第4版)
- (英)Neil Matthew Richard Stones
- 1586字
- 2021-04-09 20:04:40
2.4 管道和重定向
在深入探討shell程序設(shè)計(jì)的細(xì)節(jié)之前,我們需要先介紹一下如何才能對(duì)Linux程序(不僅僅是shell程序)的輸入輸出進(jìn)行重定向。
2.4.1 重定向輸出
讀者可能已經(jīng)對(duì)某些類型的重定向比較熟悉了,例如:

這條命令把ls命令的輸出保存到文件lsoutput.txt中。
然而,重定向所包含的內(nèi)容可比這個(gè)簡(jiǎn)單的例子所顯示的要多得多。你將在第3章學(xué)習(xí)更多關(guān)于標(biāo)準(zhǔn)文件描述符的內(nèi)容,現(xiàn)在你只需知道文件描述符0代表一個(gè)程序的標(biāo)準(zhǔn)輸入,文件描述符1代表標(biāo)準(zhǔn)輸出,而文件描述符2代表標(biāo)準(zhǔn)錯(cuò)誤輸出。你可以單獨(dú)地重定向其中任何一個(gè)。事實(shí)上,你還可以重定向其他文件描述符,但對(duì)標(biāo)準(zhǔn)文件描述符0、1、2以外的文件描述符進(jìn)行重定向的情況很少見(jiàn)。
上面的例子通過(guò)>操作符把標(biāo)準(zhǔn)輸出重定向到一個(gè)文件。在默認(rèn)情況下,如果該文件已經(jīng)存在,它的內(nèi)容將被覆蓋。如果你想改變默認(rèn)行為,你可以使用命令set -o noclobber(或set -C)設(shè)置noclobber選項(xiàng),從而阻止重定向操作對(duì)一個(gè)已有文件的覆蓋。你可以使用set+o noclobber命令取消該選項(xiàng)。你將在本章后面的內(nèi)容中看到更多的set命令選項(xiàng)。
你可以用>>操作符將輸出內(nèi)容附加到一個(gè)文件中。例如:

這條命令會(huì)將ps命令的輸出附加到指定文件的尾部。
如果想對(duì)標(biāo)準(zhǔn)錯(cuò)誤輸出進(jìn)行重定向,你需要把想要重定向的文件描述符編號(hào)加在>操作符的前面。因?yàn)闃?biāo)準(zhǔn)錯(cuò)誤輸出的文件描述符編號(hào)是2,所以使用2>操作符。當(dāng)需要丟棄錯(cuò)誤信息并阻止它顯示在屏幕上時(shí),這個(gè)方法很有用。
假設(shè)你想用kill命令在一個(gè)腳本程序里終止一個(gè)進(jìn)程,那么總是存在這種可能性,即在kill命令執(zhí)行之前,那個(gè)需要終止的進(jìn)程就已經(jīng)結(jié)束了。如果出現(xiàn)這種情況,kill命令將向標(biāo)準(zhǔn)錯(cuò)誤輸出寫(xiě)一條錯(cuò)誤信息,并且在默認(rèn)情況下,這條信息將會(huì)顯示在屏幕上。通過(guò)對(duì)標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出都進(jìn)行重定向,你就可以阻止kill命令向屏幕上寫(xiě)任何內(nèi)容了。
下面的命令將把標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出分別重定向到不同的文件中:

如果你想把兩組輸出都重定向到一個(gè)文件中,你可以用>&操作符來(lái)結(jié)合兩個(gè)輸出。如下所示:

這條命令將把標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出都重定向到同一個(gè)文件中。請(qǐng)注意操作符出現(xiàn)的順序。這條命令的含義是“將標(biāo)準(zhǔn)輸出重定向到文件killouterr.txt,然后將標(biāo)準(zhǔn)錯(cuò)誤輸出重定向到與標(biāo)準(zhǔn)輸出相同的地方。”如果順序有誤,重定向?qū)⒉粫?huì)按照你預(yù)期的那樣執(zhí)行。
因?yàn)榭梢酝ㄟ^(guò)返回碼(我們將在本章的后面對(duì)其進(jìn)行詳細(xì)介紹)來(lái)了解kill命令的執(zhí)行結(jié)果,所以通常并不需要保存標(biāo)準(zhǔn)輸出或標(biāo)準(zhǔn)錯(cuò)誤輸出的內(nèi)容。你可以用Linux的通用“回收站”/dev/null來(lái)有效地丟棄所有的輸出信息,如下所示:

2.4.2 重定向輸入
你不僅可以重定向標(biāo)準(zhǔn)輸出,還可以重定向標(biāo)準(zhǔn)輸入。例如:

很明顯,在Linux下這樣做意義不大,因?yàn)長(zhǎng)inux的more命令可以接受文件名作為參數(shù),這與Windows命令行中對(duì)應(yīng)的命令不同。
2.4.3 管道
你可以用管道操作符|來(lái)連接進(jìn)程。Linux與MS-DOS不同,在Linux下通過(guò)管道連接的進(jìn)程可以同時(shí)運(yùn)行,并且隨著數(shù)據(jù)流在它們之間的傳遞可以自動(dòng)地進(jìn)行協(xié)調(diào)。舉一個(gè)簡(jiǎn)單的例子,你可以使用sort命令對(duì)ps命令的輸出進(jìn)行排序。
如果不使用管道,你就必須分幾個(gè)步驟來(lái)完成這個(gè)任務(wù),如下所示:

一個(gè)更精巧的解決方案是用管道來(lái)連接進(jìn)程,如下所示:

如果想在屏幕上分頁(yè)顯示輸出結(jié)果,你可以再連接第三個(gè)進(jìn)程more,將它們都放在同一個(gè)命令行上,如下所示:

允許連接的進(jìn)程數(shù)目是沒(méi)有限制的。假設(shè)你想看看系統(tǒng)中運(yùn)行的所有進(jìn)程的名字,但不包括shell本身,可以使用下面的命令:

這個(gè)命令首先按字母順序排序ps命令的輸出,再用uniq命令去除名字相同的進(jìn)程,然后用grep -v sh命令刪除名為sh的進(jìn)程,最終將結(jié)果分頁(yè)顯示在屏幕上。
如你所見(jiàn),與使用一系列單獨(dú)的命令并且每個(gè)命令都帶有自己的臨時(shí)文件相比,這是一個(gè)更精巧的解決方案。但這里有一點(diǎn)需要引起注意:如果你有一系列的命令需要執(zhí)行,相應(yīng)的輸出文件是在這一組命令被創(chuàng)建的同時(shí)立刻被創(chuàng)建或?qū)懭氲模詻Q不要在命令流中重復(fù)使用相同的文件名。如果你嘗試執(zhí)行如下命令:

你最終將得到一個(gè)空文件,因?yàn)槟阍谧x取文件mydata.txt之前就已經(jīng)覆蓋了這個(gè)文件的內(nèi)容。
- Deploying Node.js
- The Modern C++ Challenge
- 深入淺出Java虛擬機(jī):JVM原理與實(shí)戰(zhàn)
- Functional Programming in JavaScript
- Kotlin Standard Library Cookbook
- 利用Python進(jìn)行數(shù)據(jù)分析(原書(shū)第3版)
- JAVA程序設(shè)計(jì)實(shí)驗(yàn)教程
- 利用Python進(jìn)行數(shù)據(jù)分析
- PHP編程基礎(chǔ)與實(shí)例教程
- OpenCV with Python By Example
- Python大學(xué)實(shí)用教程
- After Effects CC案例設(shè)計(jì)與經(jīng)典插件(視頻教學(xué)版)
- 體驗(yàn)之道:從需求到實(shí)踐的用戶體驗(yàn)實(shí)戰(zhàn)
- Developing Java Applications with Spring and Spring Boot
- 算法超簡(jiǎn)單:趣味游戲帶你輕松入門與實(shí)踐