假设我有以下脚本:-
测试.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
信号被发送到 bash下次尝试 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 并且它被终止(作为默认行为)而不是 bash运行脚本。
关于linux - Bash:使用 bash 脚本的 Head & Tail 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26461014/