2

在 bash 脚本中,我想:

  1. 将每个日志输出到一个文件中(loglowlevel.txt),
  2. 但在终端(高级)中只使它们中的少数可见,
  3. 比如说,我有 20 个高级日志和 60 个低级日志。因此,我想保持低级日志“重定向命令”免费,并且只将重定向内容重定向到高级日志。

拿 1

stdout我写了一个重定向到sterrFD的基本脚本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

这里有两个问题:

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

问题

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

4

2 回答 2

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
于 2013-02-11T18:10:58.997 回答
1

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

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例如,该版本需要命名管道( mkfifoWilliam 的解决方案中创建的对象)的可用性或通过/dev/fd.

于 2013-02-11T19:29:13.320 回答