假设我有以下脚本: -
test.sh
#!/bin/bash
command1 #prints 5 lines
command2 #prints 3 lines
Run Code Online (Sandbox Code Playgroud)
我运行脚本 test.sh|head -n5
在这种情况下会发生什么?它会运行这两个命令吗?还是会在command1之后停止?如果我用-n1调用它怎么办?
背景:我可能会问一个非常基本的问题,但实际上我注意到了一些有趣的东西.我的脚本(不同的)处理了7,000个文件,每个文件产生1行输出.完全运行脚本需要7分钟,但是在处理完第一个文件后,执行head -n1会立即提示我脚本已经终止
编辑: 以下是我的脚本
for i in $(ls filepath);do
echo "$i" # issue here
python mySript "$i" > "/home/user/output/""$i"".out"
fi
done
Run Code Online (Sandbox Code Playgroud)
删除上面的回声使脚本能够使用head -n1运行整整7分钟,但是使用echo它只打印第一行然后退出.
Tru*_*ueY 17
这是一个相当有趣的问题!谢谢发帖!
我假设head在处理前几行后会出现这种情况,因此在下次尝试时会向运行脚本SIGPIPE的bash发送信号echo $x.我使用RedX的脚本来证明这个理论:
#!/usr/bin/bash
rm x.log
for((x=0;x<5;++x)); do
echo $x
echo $x>>x.log
done
Run Code Online (Sandbox Code Playgroud)
这就像你描述的那样有用!使用t.sh|head -n 2它只会向屏幕和x.log写入2行.但陷阱SIGPIPE这种行为改变了......
#!/usr/bin/bash
trap "echo SIGPIPE>&2" PIPE
rm x.log
for((x=0;x<5;++x)); do
echo $x
echo $x>>x.log
done
Run Code Online (Sandbox Code Playgroud)
输出:
$ ./t.sh |head -n 2
0
1
./t.sh: line 5: echo: write error: Broken pipe
SIGPIPE
./t.sh: line 5: echo: write error: Broken pipe
SIGPIPE
./t.sh: line 5: echo: write error: Broken pipe
SIGPIPE
Run Code Online (Sandbox Code Playgroud)
由于stdout管道的另一端已关闭,因此已发生写入错误.任何写入闭合管道的尝试都会产生一个SIGPIPE信号,默认情况下会终止该程序(参见参考资料man 7 signal).x.log现在包含5行.
这也解释了为什么/bin/echo解决了这个问题.请参阅以下脚本:
rm x.log
for((x=0;x<5;++x)); do
/bin/echo $x
echo "Ret: $?">&2
echo $x>>x.log
done
Run Code Online (Sandbox Code Playgroud)
输出:
$ ./t.sh |head -n 2
0
Ret: 0
1
Ret: 0
Ret: 141
Ret: 141
Ret: 141
Run Code Online (Sandbox Code Playgroud)
十进制141 =十六进制8D.十六进制80表示接收到信号,十六进制0D表示SIGPIPE.因此,当/bin/echo尝试写入stdout时,它获得了一个SIGPIPE并且它被终止(作为默认行为)而不是运行脚本的bash.
很好的发现.根据我的测试,它就像你说的那样.例如,我有这个脚本只是吃cpu,让我们发现它top:
for i in `seq 10`
do echo $i
x=`seq 10000000`
done
Run Code Online (Sandbox Code Playgroud)
head -n1我们看到在第一行之后返回的命令管道脚本.这是head行为:它完成了它的工作,因此它可以停止并将控制返回给你.
输入脚本应该继续运行,但看看会发生什么:当head返回时,它的pid不再存在.因此,当linux尝试将脚本的输出发送到head进程时,它找不到进程,因此脚本崩溃并停止.
让我们用python脚本尝试一下:
for i in xrange(10):
print i
range(10000000)
Run Code Online (Sandbox Code Playgroud)
当它运行并且管道到头时你有这个:
$ python -u test.py | head -n1
0
Traceback (most recent call last):
File "test.py", line 2, in <module>
print i
IOError: [Errno 32] Broken pipe
Run Code Online (Sandbox Code Playgroud)
该-u选项告诉python自动刷新stdin和stdout,就像bash那样.所以你看到程序实际上因错误而停止.
| 归档时间: |
|
| 查看次数: |
6153 次 |
| 最近记录: |