nyx*_*x19 3 linux bash shell pipe built-in
假设以下test-pipefail.sh批处理:
#!/usr/bin/env bash
set -eo pipefail
./echoer.sh | head -n1 >/dev/null
echo "Might work with pipefail"
for i in {1..100} ; do
./echoer.sh | head -n1 >/dev/null
done
echo "Stable work with pipefail"
Run Code Online (Sandbox Code Playgroud)
使用echoer.sh内容:
#!/usr/bin/env bash
echo 'head (GNU coreutils) 8.30'
echo 'GNU bash, version 5.0.16(1)-release (x86_64-pc-linux-gnu)'
exit 0
Run Code Online (Sandbox Code Playgroud)
./test-pipefail.sh 的预期结果:
Might work with pipefail
Stable work with pipefail
Run Code Online (Sandbox Code Playgroud)
实际行为:
Might work with pipefail
Run Code Online (Sandbox Code Playgroud)
或(随机)没有输出。
如果我使用任何二进制实用程序而不是echoer.sh,管道中的 Writer 程序永远不会失败,但如果 writer 是 shell 脚本(例如,来自 glibc 二进制包的 ldd )它总是不起作用(导致 pipefail-script 退出) . 将test-pipefail.sh中的执行(./echoer.sh)替换为采购(. echoer.sh)会增加成功执行的可能性,即有时我会得到
Stable work with pipefail
Run Code Online (Sandbox Code Playgroud)
在test-pipefail.sh输出中。
head 在这样的管道中总是返回成功。删除echoer.sh 中的第二个 echo会导致成功执行,同时在单独的 shell 中进行采购和执行。
让我们将问题归结为基本问题。考虑:
$ (set -o pipefail; cat /dev/zero | head -c10; declare -p PIPESTATUS)
declare -a PIPESTATUS=([0]="141" [1]="0")
Run Code Online (Sandbox Code Playgroud)
发生的事情是,当head填满时,它完成,关闭管道。cat在这种情况下,前面的命令获取 SIGPIPE (13) 信号。因此,它将退出代码设置为 128+13=141 以指示失败。
所以,问题是当第二个进程head完成时,第一个进程是否仍在运行。有时,你echoer.sh的速度比head,有时慢。
由于我们同时处理两个进程,因此时间总是可变的。
将
./echoer.shtest-pipefail.sh 中的execution ( ) 替换为 sourcing (. echoer.sh) 会增加成功执行的概率
采购消除了初始化新 shell 的需要,这可能会导致更快的执行,因此更有可能提前完成head。
如果我使用任何二进制实用程序而不是管道中的 Writer 程序永远不会失败
echoer.sh
我cat上面的例子显示了相反的情况。那是因为cat /dev/zero程序永远不会完成,从而确保它最终会收到 SIGPIPE。
我认为结果取决于作者完成的速度。如果它完成得非常快,那么它就没有机会与SIGPIPE.
例如:
[STEP 119] # hexdump -n100 /dev/urandom | head -n1; echo '$?'=$?
0000000 eea2 36e7 24d8 15de 620c e258 f9d8 f138
$?=0
[STEP 120] # hexdump -n1000 /dev/urandom | head -n1; echo '$?'=$?
0000000 cf81 dd51 1594 88b2 c9c1 6c8a bbbd c80f
$?=0
[STEP 121] # hexdump -n1000 /dev/urandom | head -n1; echo '$?'=$?
0000000 ef2d b2d3 1024 af9f ee1e a5e6 5528 699e
$?=0
[STEP 122] # hexdump -n2000 /dev/urandom | head -n1; echo '$?'=$?
0000000 d9f7 6a0d 633b c1f7 8928 cef8 3ea9 6f5a
$?=141
[STEP 123] # hexdump -n2000 /dev/urandom | head -n1; echo '$?'=$?
0000000 c044 dbb0 c227 1836 9fb5 f03b b2d1 0605
$?=141
[STEP 124] #
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
198 次 |
| 最近记录: |