我注意到我接管的一些 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
在退出之前读取其所有输入来避免这种情况:(而不是
-q
, 一旦匹配就退出)。dpkg
您还可以使用一个命令,它会在将输出全部传递给 之前吸收输出grep
,而不会在 SIGPIPE 上生成错误。perl
是这样一个命令:perl
选项意味着:-0777
将整个输入吞入一个“行”-p
从标准输入读取每一“行”并将其打印到标准输出-e1
1
为每个输入“行”计算给定的表达式 ( )。