내 bash 쉘에 대한 로깅 함수를 직접 작성하려고 합니다. 내 목표는 명령 앞에 접두사를 붙이고 명령의 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
스크립트가 명령줄을 보기 전에 쉘이 이를 처리하고 있습니다. 처리 후에 남은 것(파이프 앞의 명령)만 전달합니다. 이러한 처리를 우회하려면 전체 명령을 인용해야 합니다.
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