如何取消缓冲从交互式命令传递到以“tee”结尾的管道中的输出?

如何取消缓冲从交互式命令传递到以“tee”结尾的管道中的输出?

     我正在对交互式命令进行故障排除,并希望:

  • 查看以原始颜色打印到屏幕上的输出,无缓冲或行缓冲(而不是堵塞-buffered,) 因为该命令生成它
  • 使用类似于tee将此命令的输出同时重定向到文件的方法,保留 - 也就是说,不乱码(例如通过传递ANSI 转义序列通过原始数据而不是正确处理它们)——它在生成的日志文件中的颜色。 (我意识到此偏好的一部分可能是不可能的,因此将其替换为以下偏好。)
  • 使用tee或类似的东西同时将此命令的输出重定向到文件
  • 在运行时按相关命令的颜色显示输出
  • 不污染生成的日志ANSI 转义序列 - 也就是说,在终端上显示输出后将它们从输出中删除,但是将其保存到日志文件中。

通常,tee -a使用我试图像魅力一样登录到此处的同类命令的输出来为我执行此操作,但是一些我在管道中遇到的奇怪的极端情况tee似乎正在破坏这种正常的、明智的行为。我做了一个少量四处挖掘看看是否有人以前遇到过类似的问题并提出解决方案,但我能够挖掘出的所有相关材料是这样的:

然而,这些资源都不是相当提供足够的提示,我想我也许可以用它们来拼凑出一些符合我所追求的东西的东西,几乎和我想要的一样快喜欢 -这样我终于可以将我需要帮助生成的日志传递给可以的人拾取当然,他们也有一些东西。
     我有尝试过在我已经阅读过的内容中,提供了基于unbuffer- 和- 的建议的一些不同变体,并且在我开始写这个问题之前正在考虑给出一些建议,但还没有抽出时间去做最后一个。我在 OS X v10.11.6“El Capitan”上使用。我试图排除故障的命令是,在哪里scriptstdbuf/usr/bin/bashHOMEBREW_BUILD_FROM_SOURCE=1 brew upgrade -vd --build-from-source mailutilsbrewHomebrew 包管理器我尝试从源代码构建并尝试升级到的 Mailutils 版本是 v3.3 (我目前有 v3.2),但我怀疑用完全切换它不同的命令那个当用作管道的一部分时会产生块缓冲输出(如果我理解的话)正确地, 将会任何shell 命令,正如我所看到的,它提到设置管道本身可能会产生块缓冲)并不能解决我的问题。我可以使用哪些工具来实现我在此处尝试捕获的日志所寻求的结果?

答案1

工艺替代1让你转变script打字稿是这样写的。

您可以使用而不是编写删除了转义序列的日志,其中任何命令运行删除它们的脚本。在相对较新版本的 macOS 或 FreeBSD 之外的其他系统上,该命令会略有不同,因为不同的实现支持不同的选项。请参阅下文了解完整详细信息。script -q >(./dewtell >>outfile) brew args...script -aq outfile brew args..../dewtellscript

到目前为止的故事(包括替代解决方案)

您的解决方案

您的brew命令将许多其他输出生成程序作为子进程运行,例如./configurescript 和make,并且您发现管道brew的输出到teewith会导致(至少其中一些子进程的)输出被缓冲并且不会出现在您的终端上实时。brew args... 2>&1 | tee -a outfile

你发现了使用script, 通过运行script -aq, 解决了这个问题标准输出终端2-k ,如果您想记录自己的输入,也可以通过该终端即使在你输入时没有回显到终端的情况下。你进一步发现杜特尔的扩展版本Gilles 的 Perl 脚本从文件中删除转义序列有效地清理生成的打字稿,将其转换为您需要的内容。

Gilles 的原始脚本和 dewtell 的扩展版本之间的区别在于,虽然它们都删除了转义序列,包括但不限于指定颜色更改的转义序列,但 dewtell 的脚本还删除了回车符($'\r',表示为^Mvim的输出中cat -v):以及退格字符( ,在 的输出中$'\b'表示为^Hin和)以及它们似乎已删除的任何字符(如果有)。vimcat -v

某些 Perl 实现的问题

您报告说该脚本需要一个“相对较新的”Perl 解释器。但它不需要任何更新的功能use或者以其他方式似乎依赖它们,并且我的一个运行 macOS 10.11.6 El Capitan 的朋友已经验证它可以与系统提供的 perl 5.8.12 一起使用,所以我不知道为什么(或者是否)你需要一个较新的 perl。我预计最多人们可以使用他们拥有的 perl。

但剧本确实失败了在 Mac OS X 10.4.11 Tiger (PPC) 上,使用系统提供的 perl 5.8.6,它错误地认为(至少在我的系统上)m不在字符类中[@-~],即使使用LC_COLLATE=Cor LC_ALL=C,即使系统提供的grepsedpython、 则不ruby存在此问题。这导致颜色指定的转义序列片段保留在输出中,因为这些序列无法匹配(?:\e\[|\x9b) [ -?]* [@-~],而是匹配了后来的替代序列\e.。和perlbrew,我在该系统上安装了 perl 5.27.5、5.8.9,甚至 5.6.2;没有人遇到这个问题。

如果确实需要或想要使用安装在其他位置的 Perl 解释器来运行脚本/usr/bin/perl,那么可以更改哈希棒顶部的线指向正确的路径;或者可以将其更改为/usr/bin/env perl所需的perl可执行文件是否第一个出现在路径中,即如果键入perl并按下它是否会运行Enter;或者可以使用脚本的文件名作为其第一个参数来显式调用解释器,例如,/usr/local/bin/perl dewtell而不是./dewtell.

保留或替换原始打字稿的方法

一些需要从打字稿中删除转义序列的用户也希望保留旧的未处理的打字稿。如果这样的用户希望处理名为 的打字稿dirty.log并将输出写入clean.log,他们将运行./dewtell dirty.log > clean.log,如有必要,替换./dewtell为运行的任何其他命令杜特尔的脚本(或他们希望使用的其他脚本)。

要“就地”修改打字稿,可以传递-iperl, running whereperl -i.orig dewtell typescripttypescript是由 生成的打字稿script.orig是要用于备份文件的任何后缀,dewtell是 Perl 脚本。或者可以改为运行,这会丢弃原始文件,因为没有提供备份后缀。这些方法并不适用于所有 Perl 脚本,但它们适用于这个脚本,因为它用于读取输入,并且perl -i dewtell typescript<><>在 Perl 方面-i

您过去常常sponge将更改写回原始打字稿。这也是一个很好且可靠的方法,尽管它要求更多实用程序被安装。

防止转义序列被记录

剩下的问题是如何编写一个首先删除了转义序列的日志。作为你说

[T]这可能还有一种将所有这些连接到一个管道中的方法,但在撰写本文时我还无法弄清楚;其他评论或答案显示如何...

使用进程替换而不是管道。

问题是script在大多数(所有?)系统上没有支持这些转换的选项。由于script写入的文件的名称是您指定的或默认的typescript(不是标准输出),因此管道传输script不会影响写入打字稿的内容。

将命令放在管道运算符 ( )script的右侧以进行管道传输|这也不是一个好主意。在您的情况下,这具体是因为brew当其标准输出是管道时,来自或其子进程的输出被缓冲,因此当您需要查看它时它不会出现。

即使这个问题得到解决,我也不知道有什么合理的方法可以使用管道1共同script完成这项任务。

但这可以通过流程替换来完成。3英寸流程替代1(也在这里解释),你写或。外壳创建一个<(command...)>(command...)命名管道并分别将其用作标准输出或输入子外壳其中command...正在运行。文本or被替换为命名管道的文件名——这就是<(command...)>(command...)代换--因此您可以将其作为参数传递给程序或将其用作重定向的目标。

  • 用于运行<(command...)command...喜欢它的输出是您要的文件的内容读自4
  • 用于运行>(command...)command...喜欢它的输入是您要的文件的内容写给4

并非所有系统都支持命名管道,但大多数系统都支持。并非所有 shell 都支持进程替换,但 Bash 支持,只要它运行在能够支持它的系统上,您的 Bash 版本就不会忽略对它的支持,并且 POSIX 模式在 shell 中被关闭。在重击中你通常可以访问进程替换,特别是如果您使用的是任何远程最新的操作系统。即使在我的 Mac OS X 10.4.11 Tiger (PPC) 系统上"$BASH_VERSION"2.05b.0(1)-release进程替换也能正常工作。

script以下是在最新的 macOS 系统上使用 s 语法时如何执行此操作的方法。

这应该适用于您的 macOS 10.11 El Capitan 系统 - 并且,通过那个联机帮助页,任何macOS系统至少可以追溯到 macOS 10.9 Mavericks可能更早:

script -q >(./dewtell >>clean.log) brew args...

记录写入终端的所有内容,包括您自己的输入如果它被回响给你,即,如果它出现在终端中,通常会出现这种情况。如果您想记录自己的输入即使它没有出现,请记住,发生这种情况的情况通常是您输入密码,那么正如您在您的答案,添加-k选项:

script -kq >(./dewtell >>clean.log) brew args...

无论哪种情况,都替换./dewtell为运行的任何命令杜特尔的脚本或您想要用来过滤输出的任何其他程序或脚本,clean.log其中包含要写入打字稿的文件名(省略转义序列),以及5包含您正在运行的命令及其参数。brew args...

覆盖或附加到日志

如果你想覆盖clean.log而不是附加到它然后使用而不是.实际的文件是由通过进程替换运行的命令写入的,因此or重定向运算符出现在.>clean.log>>clean.log>>>>( )

不要尝试使用>>(not >(,这是一个语法错误,而且毫无意义,因为>in >(for 进程替换并不意味着重定向。

不要传递-ascript以防止您的日志文件在这种情况下被覆盖,因为这只会打开命名管道在追加模式下——与打开它进行正常写入具有相同的效果——然后覆盖或追加clean.log,仍然取决于是否在子 shell 中使用或。>clean.log>>clean.log

同样,不要在内部(或任何地方)使用>&or&>或 add ,因为如果生成任何错误或警告,您会希望看到它们而不是将它们写入2>&1>( )./dewtellclean.log。该script命令自动在其打字稿中包含来自标准错误的文本;你不需要做任何特别的事情来实现这一点。

在其他操作系统上

作为您的答案说:

[S]该script命令的某些版本具有不同的语法;给出的版本适用于 OS X/macOS,因此请根据需要进行调整。

GNU/Linux

大多数 GNU/Linux 系统使用script以下提供的实现实用程序Linux。如果您想让它运行特定命令而不是启动 shell,则必须使用该-c选项并将整个命令传递为单个命令行参数to script,您可以通过将其括在引号中来实现。这与像您这样的最新 macOS 系统上的版本不同script,后者允许您将命令作为放置在输出文件名后面的多个参数自然地传递(没有像 之类的选项-c)。

所以在 Debian、Ubuntu、Fedora、CentOS 和大多数其他 GNU/Linux 系统上,您可以使用此命令(如果它有brew命令6,或将其替换为您想要运行并记录转换后的输出的任何命令):

script >(./dewtell >>clean.log) -qc 'brew args...'

script您的系统一样,在 GNU/Linux 上,-q如果您想script包含更多有关日志记录如何开始和结束的消息,请删除。即使有了这个-q选项,这个版本的script顶部仍然包含一行,说明它何时开始运行,尽管它没有显示那条线并且它没有写或显示任何关于它何时的信息停止了跑步。

没有-k选择。仅记录终端中出现的文本。7

自由BSD

macOS 中的命令script起源于 FreeBSD。所有版本都支持-a附加而不是覆盖(不过,如上所述,当您使用进程替换通过命名管道进行写入时,这并不能帮助您附加)。-a是唯一的选择,包括自由BSD 2.2.5。选项-qFreeBSD 2.2.6 中添加。选项-kFreeBSD 2.2.7 中添加

向上通过 FreeBSD 2.2.5,该script命令不允许给出特定命令,而是始终运行由SHELL环境变量给出的用户 shell,/bin/sh如果未设置该变量,则作为后备。从 FreeBSD 2.2.6 开始,可以在它将运行的命令行script而不是 shell 上给出特定命令。

script因此,FreeBSD 的更高版本(包括今天常见的版本)在调用命令的方式上与较新的 macOS 系统(例如您的系统)类似。同样,旧版本的 FreeBSD 与旧版本的 macOS 类似(见下文)。

请注意,perl在最近的任何版本中,它都不是 FreeBSD 基本系统的一部分,而且bash从来都不是。两者都可以使用软件包(例如 with pkg install perl5 bash bash-completion)或端口轻松安装。 FreeBSD中提供的系统/bin/sh不支持进程替换。

旧版本的 macOS 以及通用性较差的任何其他系统script

我在 Mac OS X 10.4 Tiger 上进行了测试,其中script接受仅有的选项-a。它不接受-q-k。它仅包含打字稿7中终端中显示的击键,与 GNU/Linux 系统上的 util-linux 版本一样。

至少在我能为每个版本的 macOS 找到可靠的文档来源之前script(据我所知,仅10.9 Mavericks 联机帮助页可以在线轻松获取),我建议 macOS 用户运行man script检查其script命令接受的语法、默认情况下的行为方式以及支持的选项。您可能想在像我这样的旧版本 macOS 上使用这些命令:

script >(./dewtell >>clean.log)
brew args...
exit

这也适用于script 在不支持很多选项的任何其他操作系统上,或者在支持其他选项但您不想使用它们的操作系统上。这种方法script是传统的方法,即启动 shell,运行 shell 中需要记录的任何命令,然后退出 shell。

假装你的命令是你的 shell 的丑陋黑客

如果您确实必须使用script它来运行单个命令而不是 shell 的新实例,那么您有时可以使用一个丑陋的 hack:您可以欺骗它,让它认为您要运行的命令实际上是您的 shell 。不过,在这样做之前你应该三思而后行,因为如果SHELL=your-command script outfileyour-command它本身实际上会查阅SHELL环境变量来检查您使用的实际 shell,随之而来的是欢闹的不幸行为。

此外,这对于由多个单词组成的命令(即要向其传递一个或多个参数的命令)来说并不容易。如果您之前在同一行上写过,那么将会成功地将的值传递到的环境中,但是整个字符串将用作命令的名称,而不仅仅是第一个单词,并且不会传递任何参数命令,而不是传递的所有其他单词。SHELL='brew args...'scriptbrew args...scriptSHELL

您可以通过编写一个 shell 脚本(称为run-brew或任何您想调用的名称)来解决此问题,该脚本运行brewargs...,然后将其作为环境变量的值传递SHELL。创建run-brewshell 脚本后,通过命令运行它script可能如下所示:

SHELL=run-brew script >(./dewtell >>clean.log)

由于上面给出的原因,我建议不要使用将命令名称分配给 的方法SHELL,除非您正在执行的操作不重要或者您确定它不会涉及使用SHELL。由于 Homebrew 执行大量且相当复杂的操作,因此我建议不要实际运行run-brew这样的脚本。 (将又长又复杂的brew命令放入脚本中并没有什么问题run-brew,只是使用SHELL=run-brewmake 来script运行它。)

然而,当用一个简单的程序代替 来测试上面显示的技术时,我确实发现这种方法有点有用。brew args...

测试和演示该技术

您可能会发现在比长命令复杂的命令上尝试其中一些方法很有用brew。我知道我做到了。

演示程序/测试输入生成器,以及使用的测试方法

我制作了这个简单的交互式 Perl 脚本,该脚本写入标准错误,在标准输出上提示用户输入其姓名,从标准输入中读取它,然后将问候语写入标准输出,并以颜色显示用户名:

#!/usr/bin/perl

use strict;
use warnings;
use Term::ANSIColor;

print STDERR $0, ": warning: this program is boring\n";
print "What's your name?  ";
chomp(my $name = <STDIN>);
printf "Hello, %s!\n", colored($name, 'cyan');

我调用它colorhi并将其放在与杜特尔的脚本,我称之为dewtell

在我自己的测试中,我在两个脚本中#!/usr/bin/perl都替换了 。 8我在 Ubuntu 16.04 LTS 中使用系统提供的 perl 5.22.1 以及 提供的版本 5.6.2 和 5.8.9 进行了测试; FreeBSD 11.1-RELEASE-p3 以及由 提供的 perl 5.24.3 和版本 5.6.2、5.8.9 和 5.27.5 ; Mac OS X 10.4.11 Tiger 带有系统提供的 perl 5.8.6 以及 . 提供的版本 5.6.2、5.8.9 和 5.27.5 。#!/usr/bin/env perlperlbrewpkgperlbrewperlbrew

我对每个 perl 版本重复了下面描述的测试,首先测试系统提供的9版本,然后使用perlbrew use暂时导致每个perlbrew提供的perl二进制文件首先出现在$PATH(例如,为了测试 perl 5.6.2,我运行了perlbrew use 5.6.2,然后下面显示了我正在测试的系统的命令)。

一位朋友在 macOS 10.11.6 El Capitan 上进行了测试,使用原始的 hashbang 行,导致使用系统提供的 perl 5.18.2,并且没有测试任何其他解释器。该测试使用了我在 FreeBSD 上测试时运行的相同命令。

除了 Mac OS X 10.4.11 Tiger 中系统提供的 perl 之外,所有这些测试均成功,由于涉及正则表达式中的字符类的奇怪错误而失败,正如我之前详细描述的,如下面的示例所示。

在Ubuntu上

在包含脚本的目录中,我在 Ubuntu 系统上运行这些命令来生成带有转义序列和我可能键入的任何退格字符的打字稿:

printf 'Whatever header you want...\n\n' >dirty.log
script dirty.log -aqc ./colorhi

我输入了Eliah,然后表现得好像我已经考虑得更好了,用退格键删除它并输入Bob from accounting。然后我按了一下Enter,受到了彩色的欢迎。然后我运行这些命令分别地生成一个没有转义序列且没有任何我的真实姓名迹象的打字稿,以完全相同的方式与其交互(包括打字和擦除Eliah):

printf 'Whatever header you want...\n\n' >clean.log
script >(./dewtell >>clean.log) -qc ./colorhi

vim以符号方式显示控制字符cat -v,并提供明亮或彩色文本的优点。这就是 所示的缓冲区view dirty.log的样子,但控制字符的表示形式为斜体,因此它们在这里脱颖而出:

Whatever header you want...

Script started on Thu 09 Nov 2017 07:17:19 AM EST
./colorhi: warning: this program is boring^M
What's your name?  Eliah^H ^H^H ^H^H ^H^H ^H^H ^HBob from accounting^M
Hello, ^[[36mBob from accounting^[[0m!^M

这就是缓冲区的样子view clean.log

Whatever header you want...

Script started on Thu 09 Nov 2017 07:18:31 AM EST
./colorhi: warning: this program is boring
What's your name?  Bob from accounting
Hello, Bob from accounting!

每个测试的解释器的结果都是相同的,当然时间戳除外。

在 FreeBSD(和 macOS 10.11.6 El Capitan)上

我在 FreeBSD 上以与在 Ubuntu 上相同的方式进行了测试,除了我使用这些命令来生成dirty.log

printf 'Whatever header you want...\n\n' >dirty.log
script -aq dirty.log ./colorhi

我使用这些命令来生成clean.log

printf 'Whatever header you want...\n\n' >clean.log
script -q >(./dewtell >>clean.log) ./colorhi

这些与我的朋友在 macOS 10.11 上测试时运行的命令相同,虽然发出的输入与我的Eliah/Bob from accounting输入略有不同,但仍然输入了一个名称,用退格键删除,然后用另一个名称替换。因此,除了名称和退格键数量之外,输出是相似的。

所有四种 Perl 实现都在 FreeBSD 上进行了测试,其中一种(系统提供的)实现在 macOS 10.11 上进行了测试,两者dirty.logclean.log显示了预期的输出。将 FreeBSD 结果与 Ubuntu 结果进行比较,差异在于缺少任何时间戳,这是由于-q.所有转义序列和回车符均已在 中成功删除clean.log,所有退格键和退格键指示删除的字符也是如此。

在 Mac OS X 10.4.11 Tiger 上

我在我的旧 Tiger 系统上以与 Ubuntu 和 FreeBSD 相同的方式进行了测试,除了我使用这些命令来生成dirty.log

printf 'Whatever header you want...\n\n' >dirty.log
SHELL=colorhi script -a dirty.log

我使用这些命令来生成clean.log

printf 'Whatever header you want...\n\n' >clean.log
SHELL=colorhi script >(./dewtell >>clean.log)

由于该系统的script命令不支持-q,结果包括(A)Script started在标题后面附加一行(二)换行符后跟Script done在每个打字稿末尾附加的一行。这两行都包含时间戳。除此之外,结果与 Ubuntu 和 FreeBSD 上的结果相同,只是系统提供的切换到青色文本和从青色文本切换的转义序列没有完全删除perl。正如预期的那样,相关行总是dirty.log以这种方式出现vim

Hello, ^[[36mBob from accounting^[[0m!^M

在系统提供的 perl 5.8.6 中,这是 中的相应行clean.log,显示6m0m,本应将其删除,留下:

Hello, 6mBob from accounting0m!

对于每个perlbrew安装的 perls,所有转义序列都被完全正确地删除,并且该行clean.log看起来像这样,就像我在 Ubuntu 和 FreeBSD 上运行的所有 Perl 解释器一样:

Hello, Bob from accounting!

笔记

1 那本手册适用于 Bash 2。许多 Bash 用户使用的是主要版本 4,并且更喜欢阅读流程替代,管道,以及其他主题当前的 Bash 手册。当前版本的 macOS 附带 Bash 3。

2 标准误几乎总是无缓冲的,无论文件或设备是什么类型。没有规定程序不能缓冲对文件描述符 2 的写入,但有一个强烈的传统不这样做,因为需要在发生错误和警告消息时实际查看它们,并且还需要查看它们根本不,即使程序异常终止而没有正确关闭或以其他方式刷新其打开的文件描述符。默认情况下,程序缓冲对标准错误的写入通常是一个错误。

3流程替代使用命名管道,也称为先进先出,它实现了与 shell 中的管道操作符相同的总体目标|,但更通用。然而,尽管这是一个管道,我认为不是一条管道,我认为它指的是 shell 的特定语法结构和相应的行为。

4如果将命名管道视为文件,则你应该,那么这实际上就是正在发生的事情。

5虽然"$COMMAND"出现在您的答案并将整个命令作为单个参数传递给script(因为双引号压制分词),您可以将命令传递给script 作为多个参数

6如与Linuxbrew,我应该承认你把我介绍给

7但是,我建议任何依赖此行为来保密敏感数据的人测试其script命令的行为,甚至可能检查生成的打字稿以确保不存在必须保护的数据。为了更加安全,请使用显示通常隐藏在屏幕上的字符的编辑器,或使用cat -v.

8带有 的版本#!/usr/bin/perl,包括colorhi所示的实现,应该可以在大多数系统上运行并做正确的事情。我#!/usr/bin/env perl在自己的测试中使用过。但是我的朋友与您(原始海报)运行的操作系统相同#!/usr/bin/perl。这实现了以最小的复杂性或潜在的怀疑来检查系统提供的 perl 是否可以工作的目标。

9在 FreeBSD 上,不存在最严格意义上的系统提供的 perl。我测试了首先安装的版本pkg

答案2

#!/usr/bin/env expect
package require Tcl 8.5
if {[llength $argv] == 0} {
    puts stderr "Usage: $argv0 logfile command \[cmd-args ..]"
    exit 1
}
set ::argv [lassign $::argv thelogfile]
log_file $thelogfile
spawn -noecho {*}$argv
interact

所有内容都应该附加(这是默认log_file记录在expect(1))到给定的日志文件中,同时interact让您可以摆弄生成的命令。用法示例:

$ rm out
$ ./yointeract out sh
$ echo hi
hi
$ printf "\033[10Ghi\n"
         hi
$ exit
$ xxd out
00000000: 2420 6563 686f 2068 690d 0a68 690d 0a24  $ echo hi..hi..$
00000010: 2070 7269 6e74 6620 225c 3033 335b 3130   printf "\033[10
00000020: 4768 695c 6e22 0d0a 1b5b 3130 4768 690d  Ghi\n"...[10Ghi.
00000030: 0a24 2065 7869 740d 0a                   .$ exit..
$ 

PS 这或多或少是该autoexpect(1)程序的作用,它也附带或至少接近expect(1)

答案3

     在与@EliahKagan 进行多次聊天后,他帮助我得出以下结论:

首先,收集以下先决条件:

  • 显然,要运行其标准输出和错误的命令;在下文中,我将其称为"$COMMAND"
  • 您将向其附加日志的文件(这样,您可以在其顶部留下注释来说明生成这些日志的内容;至少,这就是我倾向于记录事物的方式。)在下文中,我将参考此作为"$LOG_FILE"
  • 安装相对较新的版本珀尔(不是珀尔6,即不是与该语言之前的主线版本兼容)(如果您还没有)。
  • @dewtell 给出的 Perl 脚本的可执行副本他的回答这是另一个 Unix & Linux Stack Exchange 问题。在下文中,我将其称为"$RM_ANSI_ESC_SEQS_SCRIPT"
  • 安装更多实用程序(为了sponge。)

修改您的"$PATH"shell,以便您的 shell(我正在使用bash,但其他 shell 可能完全适合此处概述的过程,几乎不需要对这些说明进行任何更改)可以找到 Perl 和 moreutils。 script,这个答案中引用的另一个命令,应该已经在您的系统上可用,至少如果您像我一样在计算机上运行相对较新版本的 OS X/macOS 的话。如果不是,或者您出于任何原因想要从其他来源安装更新版本,请立即修复该问题或执行此操作。
     接下来,依次运行以下命令:

script -aq "$LOG_FILE" "$COMMAND" # Add the `k` option, either separately or as part of the group of short options already given to this command, if you want to log user input as well.  
"$RM_ANSI_ESC_SEQS_SCRIPT" "$LOG_FILE" | sponge "$LOG_FILE"

另请注意,该命令的某些版本script具有不同的语法;给出的版本适用于 OS X/macOS,因此根据需要进行调整。除此之外,仅此而已。然而,我应该补充一点,可能还有一种方法可以将所有这些连接到一个管道中,但在撰写本文时我还无法弄清楚;也欢迎其他评论或答案来说明如何做到这一点。

相关内容