各コマンドの出力を別々のログファイルに保存しますか?

各コマンドの出力を別々のログファイルに保存しますか?

teeインタラクティブに実行された各コマンドを、各コマンドごとに1つずつ一連の別々のログファイルに出力したいと思います。これを行うには、次のスクリプトを作成しました。このスクリプトは、シェルの起動時に(最後に.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

関連情報