각 명령의 출력을 별도의 로그 파일에 저장하시겠습니까?

각 명령의 출력을 별도의 로그 파일에 저장하시겠습니까?

tee대화형으로 실행된 각 명령을 각 명령마다 하나씩 일련의 별도 로그 파일에 출력하고 싶습니다 . 이를 위해 다음 스크립트를 작성했습니다. 이 스크립트는 셸이 시작될 때(끝 .bashrc) 실행할 마지막 스크립트로 설정됩니다.

date=$(date +%Y-%m-%d_%H-%M-%S)
randstr=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 4)
dir=~/log/"${date}_${randstr}"
mkdir "$dir"
i=0
while :
do
    read -e -p "user@host:$(pwd)\$ " cmd
    eval "$cmd 2>&1 | tee \"${dir}/${i}-${cmd}\"" 
    (( i++ ))
done

그러나 여기에는 몇 가지 문제가 있습니다. 첫째, 개행 문자를 만나자마자 읽기를 중지합니다. 이것이 read작동하는 방식이기 때문입니다. 나는 이런 행동을 원하지 않습니다. 나는 그것이 정확히 쉘처럼 동작하기를 원합니다. 예를 들어 글을 쓰고 ls &&누를 때 Return어떤 일을 하기 전에 더 많은 입력을 기다립니다.

이 목표를 어떻게 달성할 수 있나요? 쉘 스크립트를 통해 이를 달성하는 것이 가능/실행 가능합니까? 좀 더 전통적인 프로그래밍 언어를 사용해야 합니까? bash이를 달성하려면 패치를 해야 합니까 ?

답변1

# teeshell

date=$(date +%Y-%m-%d_%H-%M-%S)
randstr=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 4)
dir="$(echo ~/log/"${date}_${randstr}")"
mkdir "$dir"
# Redirect everything to tee and perl
exec 1> >(tee /dev/tty |
          perl -pe '                                                                          
            sub reopen {
              open(OUT,">'$dir'/".++$i);
              select OUT;
              $| = 1;
            }                     
            BEGIN {
              `echo $$ > "'$dir'"/pid`;
              reopen();                                       
              $SIG{HUP} = \&reopen;                                                           
            }') 2>&1

# wait for perl to save the pid
while [ ! -f "$dir"/pid ] ; do
    true
done

# Magic! Make perl save to a new file with a kill -HUP
PS1="[\$(kill -HUP `cat "$dir"/pid`)][\u@\h:\w]\$ "

달리기:

. teeshell

관련 정보