linux - Bash:使用 bash 脚本的 Head & Tail 行为

标签 linux bash

假设我有以下脚本:-

测试.sh

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

我用 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

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

最佳答案

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

我假设这是因为 head 在处理前几行后退出,所以 SIGPIPE 信号被发送到 下次尝试 echo $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 写入 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

输出:

$ ./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 尝试写入标准输出时,它得到一个 SIGPIPE 并且它被终止(作为默认行为)而不是 运行脚本。

关于linux - Bash:使用 bash 脚本的 Head & Tail 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26461014/

相关文章:

linux - UTF-8 文件名在 linux 终端中返回 Not Found

java - 来自 Linux-Java 线程转储的套接字信息

bash - 删除 bash 中的双重扩展名

bash - 如何将数组传递给 az appservice plan update -add 命令/参数?

bash - BASH函数中for循环中的数组

linux - 在 Linux 上提取两个字符串之间的子字符串

linux - SFTP 停止打印消息 "Uploading <file> to/path/to/file"

python - 如何在 ubuntu 后台运行 python 脚本?

linux - 按任意键从另一个脚本继续

bash - 无法使用命令的输出分配环境变量