如何在linux中进行命令录制与重放?

1. 写在前面

在本中,我们将介绍如何在 Linux 中使用 script 和 scriptreplay 命令,帮助你记录特定会话期间在终端上打印的命令及其输出。

2. 介绍

history 是一个很好的命令行工具,可以帮助用户存储以前使用过的命令,但它并不存储命令的输出。因此,script 命令就派上了用场,它提供了强大的功能,将终端上打印的所有内容记录到日志文件中。

scriptreplay 用于在终端中,根据 script 命令记录的终端数据文件和时间日志文件,重现当时用户的所有操作和命令的输出信息。即,重现播放当时终端会话发生的一切信息,而不是重新运行一遍命令。例如,用户当时在输入某条命令时,字符的键入和删除也都会被重现。非常适合用于教程演示场合。而且,在机器 A 上面使用 script 命令记录终端操作,可以在机器 B 上面使用 scriptreplay 命令重新播放。

使用场景:

  • 排查问题时候的终端交互记录;

  • 远程访问用户的行为记录;

  • 远程实时监控;

  • 排查crontab的报错问题;

3. script 记录终端

script(script – make typescript of terminal session)是一个用来录制终端会话的命令,可以捕获终端上显示的所有内容,包括输入和输出,直到退出为止。

script 命令是一个标准的 Linux 命令,适用于大多数的 Linux 发行版,如 Debian、Ubuntu、Alpine、Arch Linux、Kali Linux、RedHat/CentOS、Fedora、Raspbian 等。默认系统自带,如果系统没有安装 script 命令,可以根据发行版使用以下命令进行安装:

sudo apt-get install bsdutils          [On Debian, Ubuntu and Mint]
sudo yum install util-linux [On yum RHEL/CentOS 7]
sudo dnf install util-linux [On dnf Fedora,CentOS 8]
sudo apk add --update util-linux [On Alpine Linux]
sudo pacman -S util-linux [On Arch Linux]
sudo zypper install util-linux [On OpenSUSE]
sudo pkg install util-linux [On FreeBSD]
brew install util-linux [On OS X/macOS]

语法:

script [options] [file]

[options] 可选,用于指定 script 命令的行为;[file] 可选,用于指定保存终端信息的文件名,如果省略,则默认为 typescript;

选项:

参数 描述
-a, –append 追加模式,将输出追加到已有的文件中,而不是覆盖。多次运行 script 命令时,会在文件中添加一行表示日期和时间的分隔符;
-c, –command  执行指定的命令,而不是交互式的 shell,并将结果保存到文件中。命令执行完毕后,script 命令自动退出;
-e, –return 返回子进程的退出码,而不是 script 命令的退出码;
-f, –flush 刷新模式,每次写入时都刷新输出,而不是缓冲。这对于远程协作很有用;
–force 允许默认的输出文件 typescript 是硬链接或符号链接;
-q, –quiet 安静模式,不显示 script 命令开始和结束的提示信息,只执行并退出;
-t[], –timing[=] 记录时间信息,用于与 scriptreplay 命令配合,实现终端活动的回放。文件是可选的,用于指定保存时间信息的文件名,如果省略,则默认为 typescript.timing;

3.1 示例

示例1: 无参数运行

使用 script 命令记录终端会话,默认如果没有给出任何参数,直接键入 script 命令,会在当前目录下创建一个名为 typescript 的文件,用于保存终端操作。要停止记录,只需输入 exit 命令,script 命令就会退出。

例如:

开始:
---------------------------------------------------------------------------
root@jpzhang:~/linux# script
Script started, file is typescript

模拟操作:
---------------------------------------------------------------------------
root@jpzhang:~/linux# ls
demo typescript
root@jpzhang:~/linux# touch jpzhang.txt
root@jpzhang:~/linux# date
Sat Mar 23 18:01:18 CST 2024

退出:
---------------------------------------------------------------------------
root@jpzhang:~/linux# exit
exit
Script done, file is typescript

typescript 文件中查看刚才的终端操作:
---------------------------------------------------------------------------
root@jpzhang:~/linux# ls
demo jpzhang.txt typescript

root@jpzhang:~/linux# cat typescript
Script started on 2024-03-23 18:01:02+0800
root@jpzhang:~/linux# ls
demo typescript
root@jpzhang:~/linux# touch jpzhang.txt
root@jpzhang:~/linux# date
Sat Mar 23 18:01:18 CST 2024
root@jpzhang:~/linux# exit
exit

Script done on 2024-03-23 18:01:21+0800

示例2: 指定输出文件

使用 script 命令将终端会话保存到指定文件中;

命令:script [file]

例如:

root@jpzhang:~/linux# script script_log.txt
Script started, file is script_log.txt

root@jpzhang:~/linux# ls
demo script_log.txt

root@jpzhang:~/linux# exit
exit
Script done, file is script_log.txt

示例3: -a 参数

使用 script 命令追加终端会话到已有文件;

命令:script -a [file]

例如:

root@jpzhang:~/linux# script -a script_log.txt
---------------------------------------------------------------------------
Script started, file is script_log.txt

root@jpzhang:~/linux# whoami
root

root@jpzhang:~/linux# exit
exit
Script done, file is script_log.txt

root@jpzhang:~/linux# cat script_log.txt
---------------------------------------------------------------------------
Script started on 2024-03-23 18:09:19+0800
root@jpzhang:~/linux# ls
demo script_log.txt
root@jpzhang:~/linux# exit
exit

Script done on 2024-03-23 18:09:35+0800
Script started on 2024-03-23 18:12:09+0800
root@jpzhang:~/linux# whoami
root
root@jpzhang:~/linux# exit
exit

Script done on 2024-03-23 18:12:27+0800

该命令会将当前终端的所有活动追加到 script_log.txt 文件中,而不会覆盖已有内容。一旦执行该命令,就会在文件中添加一行表示日期和时间的分隔符,这样可以方便我们区分不同会话的记录。

示例4: -c 参数

使用 script 命令执行指定的命令并保存结果;

执行一个特定的命令,而不是交互式的 shell,并将结果保存到文件中,可以使用 -c 选项,并在后面跟上要执行的命令。这样,script 命令会在执行完命令后自动退出,不需输入 exit 命令。

有时候一个命令在终端上跑没有报错,但是放到 cron 里面的时候就会出错,就可以在 cron 里面用 script 去跑这个命令。

命令:script -c "ls -l" script_log.txt

例如:

root@jpzhang:~/linux# script -c "ls -l" script_log.txt
---------------------------------------------------------------------------
Script started, file is script_log.txt
total 4
drwxr-xr-x 2 root root 4096 Feb 22 23:41 demo
-rw-r--r-- 1 root root 0 Mar 23 18:25 script_log.txt
Script done, file is script_log.txt

示例5: -t 参数【可与 scriptreplay 命令配合】

记录终端活动的时间信息,以便于与 scriptreplay 命令配合,实现终端操作回放,可以使用 -t 选项,并在后面跟上要保存时间信息的文件名,如果省略,则默认为 typescript.timing

这样,script 命令会在执行时记录每次输出的时间间隔和字符数,并保存到时间文件中。

命令:script -t[file]

例如:

root@jpzhang:~/linux# script -tscript_time.time script_time.log
Script started, file is script_time.log

root@jpzhang:~/linux# pwd
/root/linux

root@jpzhang:~/linux# ls
demo script_log.txt script_time.log script_time.time script_time.txt

root@jpzhang:~/linux# who
bolean pts/0 2024-03-23 17:26 (10.20.0.6)

root@jpzhang:~/linux# exit
exit
Script done, file is script_time.log

script_time.time 文件存储时序信息,script_time.log 存储具体的记录内容。

注意:这里的-tscript_time.time中间没有空格。

时序信息 script_time.time:

root@jpzhang:~/linux# cat script_time.time
0.035457 60
2.730923 1
0.173779 1
0.107997 1
0.252135 2
... ...

包含两个数据字段,第一个字段表示自上次输出后经过的时间,第二个字段表示这次输出的字符数;

scriptreplay 命令来回放刚才的终端活动,例如:

root@jpzhang:~/linux# scriptreplay --timing=script_time.time script_time.log
root@jpzhang:~/linux# pwd
/root/linux
root@jpzhang:~/linux# ls
demo script_time.log script_time.time
root@jpzhang:~/linux# who
bolean pts/0 2024-03-23 17:26 (10.20.0.6)
root@jpzhang:~/linux# exit
exit

可以看到终端操作回放,包括时间间隔和输出内容。如果想调整回放的速度,可以在 scriptreplay 命令后面加上一个数,例如 2 表示加速两倍,0.5 表示减速一半。

示例6: -f 参数

在每次写入时都刷新输出,而不是缓冲,这对于远程协作非常有用。可以使用 -f 选项。这样,可以在另一个终端中实时查看 script 命令的输出文件,就像在同一个终端中一样。

这对于需要和远程同事协作,或者需要其他人审查你所做的工作时,这个技巧非常有用。

终端1:

root@jpzhang:~/linux# script -f script_log.log
Script started, file is script_log.log

root@jpzhang:~/linux# w
09:29:57 up 30 days, 9:48, 2 users, load average: 0.03, 0.01, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
bolean pts/0 10.20.0.6 09:23 1.00s 0.17s 0.05s sshd: bolean [priv]
bolean pts/2 10.20.0.6 09:29 13.00s 0.19s 0.02s sshd: bolean [priv]

root@jpzhang:~/linux# ls -l
total 16
drwxr-xr-x 2 root root 4096 Feb 22 23:41 demo
-rw-r--r-- 1 root root 640 Mar 24 09:30 script_log.log
-rw-r--r-- 1 root root 472 Mar 23 18:47 script_time.log
-rw-r--r-- 1 root root 271 Mar 23 18:47 script_time.time

root@jpzhang:~/linux# exit
exit
Script done, file is script_log.log

终端2:

root@jpzhang:~/linux# tail -f script_log.log 
Script started on 2024-03-24 09:28:53+0800
root@jpzhang:~/linux# w
09:29:57 up 30 days, 9:48, 2 users, load average: 0.03, 0.01, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
bolean pts/0 10.20.0.6 09:23 1.00s 0.17s 0.05s sshd: bolean [priv]
bolean pts/2 10.20.0.6 09:29 13.00s 0.19s 0.02s sshd: bolean [priv]
root@jpzhang:~/linux# ls -l
total 16
drwxr-xr-x 2 root root 4096 Feb 22 23:41 demo
-rw-r--r-- 1 root root 640 Mar 24 09:30 script_log.log
-rw-r--r-- 1 root root 472 Mar 23 18:47 script_time.log
-rw-r--r-- 1 root root 271 Mar 23 18:47 script_time.time
root@jpzhang:~/linux# exit
exit

Script done on 2024-03-24 09:30:35+0800

示例7: -e 参数

使用 script 命令返回子进程的退出码;

例如,当我们想要返回子进程的退出码,而不是 script 命令的退出码,可以使用 -e 选项。这样,script 命令会在执行完命令后退出,并返回命令的退出码。

root@jpzhang:~/linux# script -e -c "ls -l" /dev/null
Script started, file is /dev/null
total 16
drwxr-xr-x 2 root root 4096 Feb 22 23:41 demo
-rw-r--r-- 1 root root 1000 Mar 24 09:30 script_log.log
-rw-r--r-- 1 root root 472 Mar 23 18:47 script_time.log
-rw-r--r-- 1 root root 271 Mar 23 18:47 script_time.time
Script done, file is /dev/null

root@jpzhang:~/linux# echo $?
0

script 命令返回了 0,表示 ls -l 命令执行成功;

其他:

  • -q 选项:script 命令,在启动或者退出时,会打印 “Script started,…”,“Script done,…”,想要去除这些信息,可以使用 -q 选项来安静地执行 script 命令;

  • script 命令会在输出文件中记录终端的输入和输出,可能会导致输出文件中包含一些敏感信息,如密码或私钥等。可以使用 stty -echo 命令关闭终端的回显功能,或者使用 read -s 命令来读取不回显的输入,例如:

    root@jpzhang:~/linux# script
    Script started, file is typescript
    root@jpzhang:~/linux# stty -echo
    root@jpzhang:~/linux# Enter your password: root@jpzhang:~/linux# Your password is 123
    root@jpzhang:~/linux# exit
    exit
    Script done, file is typescript

    typescript 文件查看不含密码的终端操作:

    root@jpzhang:~/linux# cat typescript
    Script started on 2024-03-24 09:48:51+0800
    root@jpzhang:~/linux# stty -echo
    root@jpzhang:~/linux# Enter your password: root@jpzhang:~/linux# Your password is 123
    root@jpzhang:~/linux# root@jpzhang:~/linux# exit
    exit

    Script done on 2024-03-24 09:49:30+0800

4. scriptreplay 重放终端会话

语法

scriptreplay [options] [-t] timingfile [typescript [divisor]]

选项

-t, --timing file         # 记录时间日志的文件名称
-s, --typescript file # 记录终端数据信息的日志文件名称
-d, --divisor number # 表示倍速播放,把时间日志文件记录的时间间隔都除以 number
# -d 2 表示播放速度是原始输入单条命令的速度的两倍,-d 0.1 表示播放单条命令的速度减慢 10 倍
-m, --maxdelay number # 表示命令之间的最大延迟时间(单位是秒)
# -m 2 表示 command.log 中存放的两条命令之间的间隔时间如果大于两秒,则按两秒执行播放
-V, --version # 显示版本信息并退出
-h, --help # 显示帮助文本并退出

参数

  • [-t] timingfile 时间日志文件:存储时间日志信息的文件名称;

  • [typescript [divisor]] 终端数据文件:存储终端数据信息的文件名称;

示例

# 重新播放终端内容,默认第一个参数是时间日志,第二个参数是终端数据文件
scriptreplay time.file command.log
# 重新播放终端内容,播放快进速度为 1 ,命令之间最大延时为 2 秒
scriptreplay -d 1 -m 2 -t time.file -s command.log

记录终端:

root@jpzhang:~/linux# script -t 2>time.file -a -f command.log
Script started, file is command.log

root@jpzhang:~/linux# pwd
/root/linux

root@jpzhang:~/linux# uptime
10:16:04 up 30 days, 10:34, 2 users, load average: 0.00, 0.00, 0.00

root@jpzhang:~/linux# date
Sun Mar 24 10:16:07 CST 2024

root@jpzhang:~/linux# w
10:16:10 up 30 days, 10:34, 2 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 10.20.0.6 10:06 1.00s 0.25s 0.00s script -t -a -f command.log
bolean pts/2 10.20.0.6 09:29 29:56 0.20s 0.02s sshd: bolean [priv]

root@jpzhang:~/linux# exit
exit
Script done, file is command.log

重放终端:

root@jpzhang:~/linux# scriptreplay -d 1 -m 2 -t time.file -s command.log
root@jpzhang:~/linux# pwd
/root/linux
root@jpzhang:~/linux# uptime
10:16:04 up 30 days, 10:34, 2 users, load average: 0.00, 0.00, 0.00
root@jpzhang:~/linux# date
Sun Mar 24 10:16:07 CST 2024
root@jpzhang:~/linux# w
10:16:10 up 30 days, 10:34, 2 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 10.20.0.6 10:06 1.00s 0.25s 0.00s script -t -a -f command.log
bolean pts/2 10.20.0.6 09:29 29:56 0.20s 0.02s sshd: bolean [priv]
root@jpzhang:~/linux# exit
exit

输入 scriptreplay -d 1 -m 2 -t time.file -s command.log 命令,自动重放终端操作。可对比 date 命令输出信息,时间保持一致,表明是重放并不是重新执行;

感谢您花时间阅读文章!

收藏本站不迷路!



原文始发于微信公众号(滑翔的纸飞机):如何在linux中进行命令录制与重放?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/260763.html

(0)
土豆大侠的头像土豆大侠

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!