我注意到我接管的一些 CI 脚本中有一个奇怪的反模式,这基本上可以归结为以下代码:检查包中是否存在特定文件:
dpkg --contents some.deb > contents.txt
grep --quiet foo contents.txt
我尝试了明显的重构dpkg --contents some.deb | grep --quiet foo
,但我不断收到此错误:
dpkg-deb:错误:tar 子进程被信号杀死(管道损坏)
经过进一步调查,这绝对是一个时间问题。如果我使用匹配的正则表达式早期的在输入流中,我收到错误,但如果我使用专门匹配较晚行的正则表达式,则会成功。
最明显的结论是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.
答案1
dpkg
用于tar
列出包内容。当tar
无法完整处理存档时,它表示出现错误,这就是dpkg
报告的内容。这两个命令都认为无法完成任务是一个错误,并采取相应的行动。
您可以通过确保grep
在退出之前读取其所有输入来避免这种情况:
| grep foo > /dev/null
(而不是-q
,一旦匹配就退出)。
答案2
dpkg
您还可以使用一个命令,该命令将在将其全部传递给 之前吸收 的输出grep
,而不会在 SIGPIPE 上生成错误。perl
是这样一个命令:
dpkg --contents some.deb | perl -0777 -pe1 | grep --quiet foo
选项perl
的含义是:
-0777
将整个输入放入一行-p
从标准输入读取每一“行”并将其打印到标准输出-e1
1
对每个输入“行”计算给定表达式 ( )。