![如何查看已完成的终端命令的所有先前的输出?](https://linux22.com/image/1502851/%E5%A6%82%E4%BD%95%E6%9F%A5%E7%9C%8B%E5%B7%B2%E5%AE%8C%E6%88%90%E7%9A%84%E7%BB%88%E7%AB%AF%E5%91%BD%E4%BB%A4%E7%9A%84%E6%89%80%E6%9C%89%E5%85%88%E5%89%8D%E7%9A%84%E8%BE%93%E5%87%BA%EF%BC%9F.png)
我在 gnome 终端中执行了一个命令,该命令打印到终端的输出比我预期的要多。我想读取整个输出,但终端滚动在到达开头之前就停止了。
我知道我可以更改终端配置文件设置以启用无限滚动,或将输出传输到文件等。所有这些常见解决方案都适用于未来但是,输出。
如何查看已执行的命令的完整终端输出?
编辑:好吧,这是不可能的。谢谢大家!
答案1
我的经验是,评论中的共识是正确的 - 一旦超出终端的缓冲区,数据就会丢失(或者可能在尚未被覆盖的内存中) - 因此您无法追溯增加缓冲区大小。
这个答案介于评论、答案和可能对你的情况来说有点过度之间。它更像是一种建议的方法,可能会解决你的情况——特别是不知道你需要日志直到为时已晚的问题(非因果问题很难),但它不是对你问题的直接回答。
无论如何,对于评论来说,这太长了。我没有明确列出实现此方法所需的所有代码,主要是因为需要做出大量实施决策;如果您需要更详细的信息,我很乐意提供。
Script
处理起来非常不愉快
首先,script
有人建议将该实用程序作为“权宜之计”,以防止在不增加缓冲区大小的情况下丢失数据(当设置为无限制时,会产生安全隐患)。如果曾经有一个实用程序需要一些 TLC,那script
就是它。再说一次,它是由内核团队开发的。请随意阅读。
我发现script
这样做往往弊大于利(对其进行后期处理以使其更易于阅读等),因此我开始使用简化的方法来记录 stdout、stdin 和/或 stderr。从某种意义上说,这是重新创建脚本,但可以完全控制,而不是受制于硬编码的script
日志记录设置。
这种方法可以相对无缝地集成到您的 shell 会话中,并且在您确实溢出终端缓冲区的极少数情况下,您将拥有一个包含这些内容的临时文件。为了保持日志记录“干净”,您必须解决一些日常维护步骤。此外,默认情况下会存在相同的安全问题(记录所有终端输出);不过,有一种简单的方法来加密日志。
有三个基本步骤:
- 配置重定向,以便将 stdout(如果需要,还有 stderr)拆分到文件和终端。我尽量简化此示例,并且不会将 stdin 或 stderr 定向到文件 - 但是,如果您理解了 stdout 重定向示例,其余部分就很简单了。
- 配置 .bashrc 以便每当打开 shell 时启动此日志记录。
- 当给定的 shell 关闭时,使用内置的 bash
TRAP
调用将终止会话日志记录的用户代码(您可以删除文件、将其存档等)
通过这种方法,您将有效地拥有一个隐形的安全网,它将允许查看给定 shell 会话的整个历史记录(基于您重定向的内容 - 再次,为了简化,我仅显示标准输出);当您不需要它时,您甚至不知道它在那里。
细节
1.配置重定向
以下代码片段将创建文件描述符 3,它指向一个日志文件。stdout 重定向到 3,然后使用tee
将该流拆分回终端(相当于 stdout)。您可以简单地将 stderr 添加到同一个命令/日志文件,将其通过管道传输到不同的文件,或保持原样(不记录)。
logFile=$(mktemp -u)
exec 3>&1 1> >(tee $logFile >&3)
您会发现这个日志文件比脚本生成的日志文件干净得多;它不存储退格符、换行符和其他经常不需要的特殊字符。
请注意,如果您希望对日志文件进行加密,可以通过在 tee 命令后添加额外的管道阶段轻松实现openssl。
2. 自动生成日志
在 .bashrc 中添加与上述相同的代码。每次创建新的 shell 时,都会创建特定于该会话的日志文件。
export logFile=$(mktemp -u)
exec 3>&1 1> >(tee $logFile >&3)
echo "Current session is being logged in $logFile"
3. 当 shell 关闭时自动关闭日志记录
如果您希望在会话结束时删除日志文件,您可以使用 bash 内置trap
函数来检测会话是否结束并调用一个函数来处理日志文件,例如(也在 .bashrc 中)。
trap closeLog EXIT
closeLog () {
rm -f "$logFile" >/dev/null 2>&1
}
会话日志清理可以通过多种不同方式处理。当 shell 通过捕获“exit”信号关闭时,将调用此方法。此时,您可以删除日志文件、移动/重命名它,或执行任何其他操作来清理它。您还可以通过 cron 作业而不是通过 TRAP 清理日志文件(如果使用这种方法,我建议定期执行清理任务(如果您尚未为 /tmp 目录配置清理任务);因为如果 bash shell 崩溃,则不会触发 EXIT 陷阱)。
处理子 shell 时的注意事项
子 shell 会出现一种有趣的情况。如果在现有 shell 之上打开了新的交互式 shell,则会创建一个新日志,一切都会正常工作。退出该 shell(返回父级)后,将恢复对该文件的记录。如果您想更干净地解决这个问题 - 甚至可能为子 shell(交互式或其他方式)维护一个公共日志,您需要检测(在 .bashrc 中)您是否处于嵌套子 shell 中,并重定向到父级日志文件,而不是创建一个新文件。您还需要检查您是否处于子 shell 中,以便您的“trap”调用不会在退出时删除父级日志文件。您可以从 bash 环境变量 SHLVL 获取嵌套 shell 级别,该变量存储了 shell 堆栈的“深度”。
保持日志“清洁”的注意事项:
如果您确实将 stdin 重定向到日志文件,那么您最终会得到许多与脚本实用程序生成的相同的不需要的工件。这可以通过在重定向和文件之间添加过滤阶段(例如 sed/grep)来解决。只需创建一个正则表达式来删除您不想记录的任何内容。要完全清理它需要进行一些相当深入的处理(可能在写入文件之前缓冲每个新行,清理它然后写入它)。否则很难知道退格键何时是“垃圾”还是有意的。
答案2
传统方法是使用 PuTTY,保留数千行代码。还有 screen,因为 Linux(或本地)用户很少使用 PuTTY。
现在,Windows 命令行上已经有 ssh,但它已经不再有用了。