开启pipefail时,sort|sed '1,5p'与sort|head -n5行为差异原因探究
当开启pipefail选项时,
sort | sed '1,5p'与sort | head -n 5为何表现出不同行为? 核心原因:命令行为差异+shell选项的叠加作用
先明确你用到的两个关键shell开关:
set -e:只要有命令以非零状态退出,shell立刻终止set -o pipefail:管道的整体退出状态取最后一个非零退出的命令状态;如果所有命令都成功退出,管道状态为0
1. sort | head -n 5为啥会偶尔让shell退出?
sort有个特性:必须把所有输入都读完,完成排序后才会开始输出结果。head -n 5则是拿到5行输出就直接退出,同时关闭管道的读端。- 此时
sort还在尝试往管道里写剩余的排序结果,系统会给它发送SIGPIPE信号,直接终止sort,导致它的退出状态为非零。 - 因为开启了
pipefail,整个管道的状态会继承sort的非零状态,再加上set -e的规则,shell就会直接退出。 - 为啥是“有时”?如果
ps aux输出的行数≤5,sort输出完所有内容后正常退出,head也正常退出,管道状态为0,shell就不会退出;只有当输出行数超过5时,才会出现上述sort被信号终止的情况。
2. sort | sed -n "1,5p"为啥从来不会让shell退出?
sed -n "1,5p"的逻辑是:不管输入有多少内容,它会读完所有输入,仅打印前5行,直到输入流彻底结束才会退出。- 这意味着
sort可以完整地把所有排序后的结果写入管道,处理完所有输入后正常退出(状态0)。 - 整个管道里的所有命令都正常退出,状态为0,
set -e也就不会触发shell退出,无论输入行数多少都是如此。
简单验证
你可以自己测试:开启set -euxo pipefail后,执行seq 10 | sort -r | head -n 5,shell肯定会退出;而执行seq 10 | sort -r | sed -n "1,5p",shell则完全正常。
说白了,就是head拿到足够行就跑路,sort没写完就被信号终止,触发了shell的退出规则;而sed会等sort写完所有内容才退出,所以全程正常。
内容的提问来源于stack exchange,提问作者focus zheng
相关产品推荐
相关产品推荐

