我正在运行最新的 mac 操作系统并使用 zshell,但在编写 shell 脚本时遇到问题。我的大部分工作都是通过命令行完成的,并且希望有一个 bash 脚本自动保存和记录我的所有输入命令和输出。
我最明显的选择是 bash“脚本”命令,通常在命令行上启动,如下所示
script -a <filename>.txt
我写了一个shell脚本,log.sh
其内容如下:
#! /bin/sh
echo "Welcome to the jungle."
# get date
now=$(date +%Y_%m_%d)
# create filename
fname='log_'$now'.txt'
# file save location
floc=~/path/to/directory/$fname
# start script
script -a -q $floc
这将启动一个脚本,其中文件名是今天的日期并保存在指定目录中。但是,除了写入文件的内容之外,这工作得很好。我得到的不仅仅是我所期望的计划文本输入/输出,而是我认为是 ANSI 字符的内容,这些字符使文件难以阅读。
我的命令行如下所示:
~$ bash log.sh
Welcome to the jungle.
~$ echo "Hello world"
Hello world
~$ exit
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
以及它是如何记录在日志文件中的:
[1m[7m%[27m[1m[0m
]7;file://<myname>/Users/<myusername>
[0m[27m[24m[J[36m<myusername> [38;5;246m~[39m$ [K[?2004heecho "Hello world! "[?2004l
Hello world
[1m[7m%[27m[1m[0m
]7;file://<myname>/Users/<myusername>
[0m[27m[24m[J[36m<myusername> [38;5;246m~[39m$ [K[?2004heexit[?2004l
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
我知道创建文件后有几种方法可以处理 ANSI 键,例如使用命令cat
显示文本,或使用 perl 脚本删除键;但是,cat
当我尝试查看大文件时,使用该命令很烦人,而且必须手动清理文件也很乏味。有什么方法可以记录我的命令行输入和输出没有ANSI 键?
谢谢你!
答案1
简单的方法是查看带有less -R
.这并不完全是您所要求的,但无论如何可能会有所帮助。
答案2
这似乎有效:
#!/usr/bin/env zsh
{
# Create a named pipe, using a temp file name.
mkfifo -m 600 ${fifo::=$(mktemp -u)}
logFile="~/logs/log-$(date +%F-%H-%M-%S).txt"
print "Logging to $logFile"
# Launch the filter in the background (&), so it will
# run in parallel with the script utility.
# This will read from the named pipe, remove the ansi
# color escapes, and write the result to the log.
# (perl source: https://superuser.com/a/1388860).
perl -pe 's/\e\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]//g;
s/\e[PX^_].*?\e\\//g;
s/\e\][^\a]*(?:\a|\e\\)//g;
s/\e[\[\]A-Z\\^_@]//g;' \
< $fifo > ${~logFile} &
# Get the process id of the background process.
fifoPid=$!
# Launch the script utility, capturing data from the
# interactive shell. -F ensures writes are immediately
# available in other processes.
script -q -F $fifo
# script -q -F $fifo bash
# The background process will end when the script
# utility closes its handle to the fifo, i.e. when the
# shell launched by 'script' exits. But it may not exit
# immediately, so it could be running when we get to
# this point. This will bring it to the foreground, just
# in case some other actions follow this script.
wait $fifoPid
} always {
# cleanup temp fifo.
if [[ -p $fifo ]] rm $fifo
}
这使用了一个命名管道以便script
实时过滤输出。您还可以在启动的 shell 程序中将清理过滤器作为后处理来运行script
,但这并不是那么有趣。