如何对管道命令进行分组以使用包装函数进行处理

如何对管道命令进行分组以使用包装函数进行处理

我正在尝试为我的 bash shell 自己编写一个日志记录功能。我的目标是拥有一个可以作为命令前缀的函数,并将命令的 stdout 和 stderr 传递到日期日志文件。目前我有:

logme()
{
    FULL_COMMAND=$@

    for EXE in ${FULL_COMMAND}
    do
        case $EXE in
            nohup) continue;;
            time) continue;;
        esac
        break
    done

    mkdir -p logs
    LOGNAME=$(basename ${EXE})_$(date +%Y-%m-%d_%H:%M:%S)

    echo $FULL_COMMAND > logs/${LOGNAME}.e.log
    echo '============' >> logs/${LOGNAME}.e.log
    $FULL_COMMAND > logs/${LOGNAME}.o.log 2>> logs/${LOGNAME}.e.log
}

这似乎适用于简单的情况。跑步:

$ touch file1.txt
$ touch file2.txt
$ touch file3.txt

$ logme ls -lh

生成一个包含 2 个日期文件的日志目录。

$ more logs/ls_2017-05-08_16\:05\:36.e.log 
ls -lh
============

$ more logs/ls_2017-05-08_16\:05\:36.o.log 
total 6.5K
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file1.txt
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file2.txt
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file3.txt
drwxr-xr-x 2 aholman compbio 92 May  8 16:05 logs

但是,在命令中添加管道的行为并不像我希望的那样。日志记录似乎与第一个命令分组,并且 logme 的输出通过管道传递。当然,logme 没有输出,因为整个目的是将其定向到文件。

$ logme ls -lh | grep -v file2
$ more logs/ls_2017-05-08_16\:12\:15.e.log 
ls -lh
============

$ more logs/ls_2017-05-08_16\:12\:15.o.log 
total 6.5K
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file1.txt
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file2.txt
-rw-r--r-- 1 aholman compbio  0 May  8 16:05 file3.txt
drwxr-xr-x 2 aholman compbio 92 May  8 16:12 logs

有没有一种好方法对整个命令进行分组,以便整个命令都由 logme 处理?

答案1

在脚本看到命令行之前,shell 正在对其进行处理。它只传递处理后剩下的内容(管道之前的命令)。要绕过此类处理,您需要引用整个命令:

logme 'ls -lh | grep -v file2'

不过你有一个新问题。该命令位于字符串中,无法直接执行。一种方法是使用 eval

eval "$FULL_COMMAND" > logs/${LOGNAME}.o.log 2>> logs/${LOGNAME}.e.log

但 eval 应谨慎使用,因为它很容易被利用:http://mywiki.wooledge.org/BashFAQ/048

相关内容