5

使用管道要注意的几个点

 2 years ago
source link: https://www.lujun9972.win/blog/2018/04/28/%E4%BD%BF%E7%94%A8%E7%AE%A1%E9%81%93%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E5%87%A0%E4%B8%AA%E7%82%B9/index.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用管道要注意的几个点

  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 $?
    

    若你想要知道管道中每条命令的执行情况,则需要查看 PIPESTATUE 变量

    wrong command1 |[[ "a" == "b" ]] |true
    echo "${PIPESTATUS[0]}" "${PIPESTATUS[1]}" "${PIPESTATUS[2]}"
    
  3. 打开命名管道时,若只打开它的一端,则该操作会被挂起,直到它的读写两端都被打开。

    下面操作会被挂起

    mkfifo t
    exec 4>t
    

    而下面操作不会挂起

    mkfifo t
    exec 4<>t
    
  4. 有些程序会把输出内容缓存起来,直到缓存区满了或者收到结束符号才将内容真正输出。 当使用这种程序写入命名管道时,要特别注意,确保程序真的有把内容输出道命名管道,而不是缓存起来,否则很容易导致操作挂起
  5. 不要真的把命名管道当成文件来用,当命名管道的读写两端都关闭后,里面的内容会被清掉。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK