bash:echo:写错误:系统调用中断


9

我想生成一个包含所有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)-发行版(x86_64-pc-linux-gnu)

Debian GNU / Linux 9.6(延伸)

Linux内核:4.19.0#2 SMP Thu Nov 1 15:31:34 EET 2018 x86_64 GNU / Linux


2
我禁不住觉得这种方式不会比效率更高seq -w 0 99999999
库萨兰达

1
然后问题是不完整/不正确/写得不好或其他问题。因为该脚本(在完成时})正常工作。@ GAD3R
艾萨克(Isaac)

1
注意:我几乎可以按需触发这些错误。它们通常在我调整konsole窗口大小时出现。在我看来,这种调整大小几乎是足够的,但不是必需的。
卡米尔Maciorowski

我可以删除| tee result.txt,但仍然会收到错误消息。
ctrl-alt-delor

另一个注意事项:外部可执行文件(/bin/echo在我的情况下)而不是echo内置文件,使该函数不受此问题的影响(或至少较不容易受到影响)。
卡米尔Maciorowski

Answers:


6

write error: Interrupted system call在执行脚本时更改控制台窗口大小时,将生成特定错误。

正在执行:

 trap '' SIGWINCH

会避免它。

请注意

 seq 99999999 >result.txt; wc -l <result.txt

既可以更快,又可以避免SIGWINCH问题。


5
那么怎么回事?,为什么我以前没看过?,为什么写错误,正确的做法?
ctrl-alt-delor

4

这实际上是一个错误[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()printfecho

EINTR(“中断的系统调用”)不是一种指示错误情况的方法,而是一种允许程序员将主程序中的阻塞读/写/等与信号处理结合在一起的黑客手段。它永远不会泄漏给用户。

该错误不会经常出现,因为要正确设置条件是一项壮举:write()应该由内置函数(而不是外部命令)完成,应该填充管道缓冲区(另一个为读取器)到底应该是多少慢或从管道根本不读,但还活着),和脚本应该使用陷阱或终端窗口应该调整。

并且由于实现工件的多样性,这只会影响被中断的write()s,而不影响read()s或open()s(例如open(),对命名管道/ fifo 的阻塞)。

[1]这种形式已经在一段时间前报道过

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.