击:头和放大器;与bash脚本尾部行为 [英] Bash: Head & Tail behavior with bash script

查看:128
本文介绍了击:头和放大器;与bash脚本尾部行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下脚本: -

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆