我正在尝试为我的 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