我想将tee
每个交互式执行的命令输出到一系列单独的日志文件,每个命令一个。为此,我编写了以下脚本,该脚本将设置为 shell 启动时最后运行的脚本(结束.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
工作原理。我不想要这种行为。我希望它的行为与 shell 完全相同,因此,例如,当我编写ls &&
并按下时Return,它会在执行任何操作之前等待更多输入。
我怎样才能实现这个目标?通过 shell 脚本实现这一点是否可能/可行?我应该使用更传统的编程语言吗?我是否应该打补丁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