Shell

dpkg --contents 是否無法處理 SIGPIPE?

  • March 2, 2022

我注意到我接管的一些 CI 腳本中有一個奇怪的反模式,這基本上歸結為這段程式碼檢查包中是否存在特定文件:

dpkg --contents some.deb > contents.txt
grep --quiet foo contents.txt

我嘗試了明顯的重構dpkg --contents some.deb | grep --quiet foo,但我不斷收到此錯誤:

dpkg-deb: 錯誤: tar 子程序被信號殺死 (Broken pipe)

從更多的調查來看,這絕對是一個時間問題。如果我使用在輸入流早期匹配的正則表達式,我會收到錯誤,但如果我使用專門匹配後期行的正則表達式,它會成功。

最明顯的結論是dpkg(或可能tar)對 SIGPIPE 做錯了什麼。這是一個已知的問題?

平台:

# lsb_release --all
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.6 LTS
Release:    18.04
Codename:   bionic
# dpkg --version
Debian 'dpkg' package management program version 1.19.0.5 (amd64).
This is free software; see the GNU General Public License version 2 or
later for copying conditions. There is NO warranty.
# tar --version
tar (GNU tar) 1.29
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by John Gilmore and Jay Fenlason.

dpkg用於tar列出包內容。當tar無法完整處理檔案時,它表示一個錯誤,這dpkg就是報告的內容。兩個命令都認為無法完成任務是錯誤,並採取相應的行動。

您可以通過確保grep在退出之前讀取其所有輸入來避免這種情況:

| grep foo &gt; /dev/null

(而不是-q, 一旦匹配就退出)。

dpkg您還可以使用一個命令,它會在將輸出全部傳遞給 之前吸收輸出grep,而不會在 SIGPIPE 上生成錯誤。perl是這樣一個命令:

dpkg --contents some.deb | perl -0777 -pe1 | grep --quiet foo

perl選項意味著:

  • -0777將整個輸入吞入一個“行”
  • -p從標準輸入讀取每一“行”並將其列印到標準輸出
  • -e1``1為每個輸入“行”計算給定的表達式 ( )。

引用自:https://unix.stackexchange.com/questions/692612