1、管道中的每个命令都是在自己的子 shell 中执行的,因此管道中的命令不要尝试去修改父 shell 中的变量,那样是无效的。
last_line='NULL'
seq 1 2 | while read line; do
last_line="${line}"
# echo ${last_line}
done
# This will output 'NULL'
echo "${last_line}"
正确的做法是改成
last_line='NULL'
while read line; do
last_line="${line}"
done< <(seq 1 2) # 注意< 和 < 之间有个空格
# This will output '2'
echo "${last_line}"
2、管道的返回值只由最后哪个命令的返回值来决定,除非指定了 pipefail
比如,下面这个命令的 $? 会是 0
wrong command1 |[[ "a" == "b" ]] |true
echo $?
0
若指定了 pipefail 选项,则管道的返回值最后的那个执行失败的命令来决定
set -o pipefail
wrong command1 |[[ "a" == "b" ]] |true
echo $?
1
若你想要知道管道中每条命令的执行情况,则需要查看 PIPESTATUE 变量
wrong command1 |[[ "a" == "b" ]] |true
echo "${PIPESTATUS[0]}" "${PIPESTATUS[1]}" "${PIPESTATUS[2]}"
127 1 0
3、打开命名管道时,若只打开它的一端,则该操作会被挂起,直到它的读写两端都被打开。
下面操作会被挂起
mkfifo t
exec 4>t
而下面操作不会挂起
mkfifo t
exec 4<>t
4、有些程序会把输出内容缓存起来,直到缓存区满了或者收到结束符号才将内容真正输出。 当使用这种程序写入命名管道时,要特别注意,确保程序真的有把内容输出道命名管道,而不是缓存起来,否则很容易导致操作挂起
5、不要真的把命名管道当成文件来用,当命名管道的读写两端都关闭后,里面的内容会被清掉。

