击:头和放大器;与bash脚本尾部行为 [英] Bash: Head & Tail behavior with bash script
问题描述
假设我有以下脚本: -
Suppose I have following script:-
test.sh
#!/bin/bash
command1 #prints 5 lines
command2 #prints 3 lines
我运行 test.sh脚本|头-n5
将在此情况下,会发生什么?它运行两个命令?还是会命令1后停下来?
如果我把它叫做 -n1
What will happen in this case? Will it run both the commands? or will it stop after command1? What if I call it with -n1?
背景:我可能会问一个很基本的问题,但实际上我注意到一些有趣的事情。我的脚本(不同的)正在处理7000文件,每个文件产生1路输出。它需要7分钟完全但这样做运行脚本的头-n1 给我的提示立刻像脚本只处理第一个文件后终止
Background: I might be asking a very basic question, but I actually noticed something interesting. My script(different one) was processing 7,000 files and each file produces 1 line of output. It takes 7 minutes to run the script completely but doing head -n1 gave me prompt immediately like the script has terminated after processing first file only
编辑:
下面是我的脚本
Following is my script
for i in $(ls filepath);do
echo "$i" # issue here
python mySript "$i" > "/home/user/output/""$i"".out"
fi
done
删除回声上面使脚本是头运行完整7分钟-n1 ,但与它呼应只是打印第一行然后退出。
Removing echo above enables the script to run full 7 minute with head -n1, but with echo it just prints first line then exit.
推荐答案
这是一个相当有趣的问题!感谢张贴了!
This is a fairly interesting issue! Thanks for posting it!
我认为出现这种情况的头
处理第几行,所以 SIGPIPE
信号后退出被送到的bash 运行脚本时它会尝试回声$ X
下一次。我用RedX的脚本来证明这个理论:
I assumed that this happens as head
exits after processing the first few lines, so SIGPIPE
signal is sent to the bash running the script when it tries to echo $x
next time. I used RedX's script to prove this theory:
#!/usr/bin/bash
rm x.log
for((x=0;x<5;++x)); do
echo $x
echo $x>>x.log
done
这工作,因为你描述的!使用 t.sh |头-n 2
写入只有2线将屏幕和x.log。但是诱捕SIGPIPE这种行为改变...
This works, as You described! Using t.sh|head -n 2
it writes only 2 lines to the screen and to x.log. But trapping SIGPIPE this behavior changes...
#!/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
输出:
$ ./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
作为标准输出
发生的写入错误的管的另一端是封闭已经关闭。而任何试图写入封闭管道引起SIGPIPE信号,默认终止程序(请参阅人7信号
)。该x.log现在包含5行。
The write error occurs as stdout
is already closed as the other end of the pipe is closed. And any attempt to write to the closed pipe causes a SIGPIPE signal, which terminates the program by default (see man 7 signal
). The x.log now contains 5 lines.
这也解释了为什么 /斌/回声
解决了这个问题。见下面的脚本:
This also explains why /bin/echo
solved the problem. See the following script:
rm x.log
for((x=0;x<5;++x)); do
/bin/echo $x
echo "Ret: $?">&2
echo $x>>x.log
done
输出:
$ ./t.sh |head -n 2
0
Ret: 0
1
Ret: 0
Ret: 141
Ret: 141
Ret: 141
十进制141 =六角8D。十六进制80表示被接收的信号,六角0D为SIGPIPE。因此,当 /斌/回声
试图写入stdout它得到一个SIGPIPE并终止(默认行为),而不是的庆典运行脚本。
Decimal 141 = hex 8D. Hex 80 means a signal was received, hex 0D is for SIGPIPE. So when /bin/echo
tried to write to stdout it got a SIGPIPE and it was terminated (as default behavior) instead of the bash running the script.
这篇关于击:头和放大器;与bash脚本尾部行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!