我想生成一个包含所有 8 位数字的排序列表 - 从 00000000 到 99999999。我在 shell 中输入:
f() {
while IFS="" read -r line; do
for i in {0..9}; do
echo "$line$i";
done;
done
}
echo | f | f | f | f | f | f | f | f | tee result.txt | wc -l
响应是
bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
99998890
为什么我会收到这三个错误和格式错误的 result.txt ?
我用
GNU bash,版本 4.4.12(1)-release (x86_64-pc-linux-gnu)
Debian GNU/Linux 9.6(延伸)
Linux 内核:4.19.0 #2 SMP 11 月 1 日星期四 15:31:34 EET 2018 x86_64 GNU/Linux
答案1
write error: Interrupted system call
当执行脚本时更改控制台窗口大小时,会生成特定错误。
做一个:
trap '' SIGWINCH
会避免它。
请注意,一个
seq 99999999 >result.txt; wc -l <result.txt
既会更快,也会避免这个SIGWINCH
问题。
答案2
这实际上是一个错误[1]在 中bash
,并且它不仅发生在 上SIGWINCH
,而且还发生在设置了陷阱的任何信号上:
{ pid=$BASHPID; trap : USR1; (sleep 1; kill -USR1 $pid) &
printf %0100000d 1; } | sleep 3600
bash: printf: write error: Interrupted system call
发生这种情况是因为bash
未能 a) 设置其信号处理程序SA_RESTART
(处理程序除外SIGCHLD
),或 b)在调用和内置函数EINTR
时处理该信号处理程序。write()
printf
echo
EINTR
(“中断的系统调用”)不是一种指示错误情况的方法,而是一种允许程序员将阻塞读/写等与主循环中的信号处理结合起来的方法。它绝对不应该泄露给用户。
这个错误不会太频繁地出现,因为获得正确的条件是一项相当大的壮举:应该write()
由内置(不是通过外部命令),它应该填满管道缓冲区(另一端的阅读器应该是很多速度较慢或根本不从管道读取但还活着),并且脚本应使用陷阱或应调整终端窗口的大小。
并且由于不同的实现工件,这仅影响中断的write()
s,而不影响read()
s 或open()
s(例如open()
命名管道/fifo 的阻塞)。
[1]这种形式已经存在报道前一段时间。