如何在bash中设置两个重定向级别?

时间:2013-02-11 17:57:46

标签: bash io-redirection

在bash脚本中,我想:

  1. 将每个日志输出到文件(loglowlevel.txt),
  2. 但是在终端(高级别)中可以看到只有少数
  3. 我有20个高级日志和60个低级日志。因此,我想保留低级日志“redirection-command”,并将重定向内容仅限于高级日志。
  4. 取1

    我写了一个基本脚本,将stdoutsterr重定向到FD 3. loglowlevel.txt已正确填充。但我仍然坚持指定高级日志的选项。

    #!/bin/bash - 
    
    # create fd 3
    exec 3<> loglowlevel.txt
    # redirect stdout and stderr to fd 3
    exec 1>&3
    exec 2>&3
    
    # high-level logs' redirection below is wrong
    echo "high-level comment" 3>&1
    
    # low-level logs should remain redirection-free, as below
    echo "low-level comment"
    ls notafile
    
    # close fd 3
    3>&-
    

    这是它的作用:

    $ redirect.sh
    $ cat loglowlevel.txt 
    low-level comment
    ls: cannot access notafile: No such file or directory
    

    我也期望在终端上打印high-level comment

    拿2

    第二个脚本,不同的策略:

    #!/bin/bash - 
    
    function echolowlevel() {
        echo $1 &>loglowlevel.txt
    }
    
    function echohighlevel() {
        echo $1 |& tee loglowlevel.txt
    }
    
    echohighlevel "high-level comment 1"
    echolowlevel "low-level comment 1"
    echohighlevel "high-level comment 2"
    ls notafile
    

    这是它的作用:

    $ redirect.sh 
    high-level comment 1
    high-level comment 2
    ls: cannot access notafile: No such file or directory
    $ cat loglowlevel.txt 
    high-level comment 2
    

    这里有两个问题:

      来自ls
    1. 错误消息打印在终端中,而我只在loglowlevel.txt中需要它。
    2. high-level comment 1已在loglowlevel.txt
    3. 中被吃掉

      问题

      我更喜欢 Take 1 背后的想法。但是如何在保留两个high-level comment命令的同时将exec输出到stdout?

2 个答案:

答案 0 :(得分:3)

#!/bin/sh

FIFO=/tmp/fifo.$$  # or use tmpfile, or some other mechanism to get unique name
trap 'rm -f $FIFO' 0
mkfifo $FIFO
tee -a loglowlevel.txt < $FIFO &

exec >> loglowlevel.txt
exec 3> $FIFO

echo high-level >&3  # Appears on original stdout and in loglowlevel.txt
echo low-level       # Appears only in loglowlevel.txt

答案 1 :(得分:1)

William Pursell答案的简短版本,用于支持进程替换的shell和操作系统:

exec 3>> >(tee -a loglowlevel.txt)
exec >> loglowlevel.txt

echo high-level >&3  # Appears on original stdout and in loglowlevel.txt
echo low-level       # Appears only in loglowlevel.txt

在此示例中,写入文件描述符3有效地写入后台tee进程的标准输入,该进程附加到文件“loglowlevel.txt”。

对此功能的支持各不相同。它不是POSIX标准的一部分,但它至少由bashkshzsh提供。每个shell都需要一些操作系统支持。例如,bash版本需要命名管道的可用性(在威廉的解决方案中由mkfifo创建的对象)或通过/dev/fd访问打开的文件。