当前位置: 首页 > 面试题库 >

Bash:bash脚本的头尾行为

谯嘉胜
2023-03-14
问题内容

假设我有以下脚本:

test.sh

#!/bin/bash
command1  #prints 5 lines
command2  #prints 3 lines

我运行脚本 test.sh|head -n5

在这种情况下会发生什么?它会同时运行两个命令吗?还是会在command1之后停止?如果我用 -n1 html" target="_blank">调用该怎么办?

背景:
我可能会问一个非常基本的问题,但实际上我注意到了一些有趣的事情。我的脚本(不同的脚本)正在处理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

删除上面的 echo 可使脚本使用 head -n1 运行整整7分钟,但使用echo则仅打印第一行,然后退出。


问题答案:

这是一个相当有趣的问题!感谢您发布!

我假设这是head在处理了前几行后在退出时发生的,所以当它尝试下一次时,SIGPIPE信号会发送到运行该脚本的bashecho $x。我使用RedX的脚本来证明这一理论:

#!/usr/bin/bash
rm x.log
for((x=0;x<5;++x)); do
    echo $x
    echo $x>>x.log
done

如您所描述的那样,这有效!使用t.sh|head -n 2它仅将两行写入屏幕和x.log。但是捕获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

输出:

$ ./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

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

输出:

$ ./t.sh |head -n 2
0
Ret: 0
1
Ret: 0
Ret: 141
Ret: 141
Ret: 141

十进制141
=十六进制8D。十六进制80表示已接收到信号,十六进制0D用于SIGPIPE。因此,当/bin/echo尝试写入stdout时,它得到了SIGPIPE并被终止(作为默认行为),而不是bash运行脚本。



 类似资料:
  • 问题内容: 在Python中,有没有一种方法可以使代码块始终在程序的末尾执行(除非? 我们有一个Jenkins项目,它会在构建过程中启动python脚本。如果开发人员决定中止这项工作,那么就会遗留很多工件,这些工件会(并且正在)影响未来的构建。 无论如何,要确保运行python脚本的清理部分? 问题答案: 使用出口处理程序。这是python docs 的示例:

  • 问题内容: 如何在python中实现诸如“ head”和“ tail”命令之类的东西,并通过文本文件的行向后读取? 问题答案: 这是我的个人文件类;-) 用法示例:

  • 问题内容: 我知道这个问题被问过很多次,但是我没有找到答案。那么,为什么建议在body标签的末尾添加脚本以更好地渲染呢? 从Udacity课程和CSSOM准备就绪后开始渲染。JS是HTML解析阻止程序,并且CSSOM准备好后,任何脚本都会启动。 因此,如果我们得到: CRP为: 如果脚本在头: CRP将相同: 这个问题仅与“同步”脚本有关(没有async / defer属性)。 问题答案: 从历史

  • 问题内容: 我试图像通过CGI脚本一样设置HTTP标头。 在: 或在: 两者都对输出没有影响。 如何才能做到这一点? 编辑 我还使用包在中尝试了以下方法: 但是我得到了错误: 问题答案: 问题1: 如果您的脚本返回有效的HTTP返回码(如),则G-WAN会构建相应的HTTP标头,除非它们已经存在(从此处开始)。 因此,要强制使用脚本语言 (不支持诸如C,C ++,D和Objective-C之类的支

  • 问题内容: 与其他语言(例如或)的解释器类似,如何指示在脚本结尾处终止? 跟随命令 带脚本 版画 并等待其他命令。我希望它在文件末尾立即停止。 我正在寻找比脚本结尾更优雅的内容。 问题答案: 在脚本内部,使用jshell命令。这将在脚本末尾退出jshell。 检查此参考https://docs.oracle.com/javase/9​​/jshell/introduction-jshell.htm

  • 问题内容: 假设您有一个txt文件,同时查看文件的前10行和后10行的命令是什么? 即,如果文件长200行,则可以一次性查看1-10行和190-200行。 问题答案: 您可以简单地: 如果由于某种原因需要使用管道,则如下所示: 注意:如果file.txt中的行数小于默认的head行+默认的tail行,则将打印重复的行。