Windows XP Windows 7 Windows 2003 Windows Vista Windows教程綜合 Linux 系統教程
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟件教程
 Windows教程網 >> Linux系統教程 >> Linux教程 >> Linux系統下管道被接受方關閉的問題解決

Linux系統下管道被接受方關閉的問題解決

日期:2017/2/7 16:57:49      編輯:Linux教程

Linux shell中的管道|是非常方便的功能,可以將一個程序的輸出作為另外一個程序的輸入,這樣我們可以將多個命令“拼”在一起,省去了臨時文件的繁瑣。windows中也有類似的用法,比如dir |more,學過dos命令的應該都知道吧。


既然是管道,那麼就有一個入口和一個出口,各自對應一個應用程序,正常的情況下,入口應用程序的輸出應當被出口應用程序全部接受,但在一些特殊情況,出口應用程序會提前關閉管道,比如在查詢svn的更新日志,只取前己行的時候:


$ svn log |head

----------------

r137 | Fwolf | 2007-05-28 13:38:47 +0800 (Mon, 28 May 2007) | 4 lines


更新記錄。


svn: Write error: Broken pipe


由於head只需要用到輸入的前10行(默認行數,也可由用戶指定),再接收剩下的輸出也是多余,便提前關閉了管道,管道入口的應用程序svn發現之後,便報錯退出了。在這個例子中,錯誤信息非常清楚,但不是所有應用程序都這樣的,比如下面這個:


$ find . -name "*rc" |xargs -i cat {}|head -1

[Desktop]

xargs: cat: terminated by signal 13


錯誤信息似乎並不太好理解,實際上它的意思是:xargs發現它的子進程cat由於信號13被中止了。由於xargs本身屬於循環操作,發現錯誤之後就停止了循環,這是其一;信號13是在cat試圖向一個已關閉的pipe管道中寫數據的時候,系統產生的,cat收到之後就停止了。類似於在cat輸出的過程中,用戶按下ctrl+c的效果。


如何避免這種問題呢?很簡單,管道後面使用不會提前關閉管道的程序即可,尤其是結合xargs使用的時候,它發現出錯就不繼續了。比如要用到head可以這樣:


$ cat file |head -1


雖然cat仍然會被signal 13關閉,但bash是不會報錯的,所以也只能針對一個文件進行操作,即使是使用了通配符也只能head到第一個文件。如果要加上對文件的遍歷,可以用到for:


$for file in .*rc;do cat $file |head -1;done


cat依然會被關閉,但是for不會理會它,繼續循環。head也可以直接指定文件名,這樣我們就可以拋開cat了:


$find . -name "*rc" |xargs -i head -n1 {}


個人認為這是一種最完美的解決方式,即可以用到find強大的搜索指令,還不會涉及到管道的問題。不過如果文件名沒有什麼特殊要求,還有一種更簡單的方式:


$head -n1 .*rc


在head的參數中直接用通配符指定文件。

Copyright © Windows教程網 All Rights Reserved