`less`命令显示输出所需的时间

5
我有一个脚本会输出大量内容,在点T处暂停几秒钟。

现在我使用less命令来分析脚本的输出。所以我执行命令./script | less。我让它运行足够长时间以便脚本完成执行。

现在我通过按下Pg Down键来浏览less命令的输出。令人惊讶的是,当我在输出的点T滚动时,我再次注意到了几秒钟的暂停。

脚本不需要任何输入,而且在我开始分析less的输出之前一定已经完成了。

有人能解释一下为什么在脚本完成执行后,仍可以在less的输出中注意到几秒钟的暂停吗?

也许输出的那个特定页面有大量的文本,例如如果存在极长的水平线。 - ninjagecko
5个回答

8
您的脚本通过管道与less通信。管道是一个连接两个端点(您的脚本和less程序)的内存流,前者向其写入输出,后者从其读取。
由于管道在内存中,如果它们无限增长将不好处理。因此,默认情况下,在任何给定时刻,管道中可以存在的数据量有一个限制(已写入但尚未读取)。在Linux上,默认值为64k。如果管道已满,并且您的脚本尝试向其写入,则写入操作会被阻塞。因此,您的脚本实际上并没有执行,它在执行write()调用时停止了。 如何克服这个问题呢?调整默认值是一个糟糕的选择;相反,使用的方法是在读取器中分配缓冲区,以便它将内容读入缓冲区,释放管道,从而让写入程序继续工作,但只显示给您(或处理)一部分输出。 less具有这样的缓冲区,并且默认情况下会自动扩展它,但它不会在后台填充它,它只会在您读取输入时填充它。
那么,如何解决您的问题?读取文件直到结束(就像您通常按G键一样),然后返回开头(就像您通常按g键一样)。问题在于,您可以通过命令行指定这些命令,如下所示:
./script | less +Gg

然而,您需要注意的是,必须等到整个脚本的输出加载到内存中后,才能查看它,因此您无法一次性查看它。使用less不够复杂。但是,如果这确实是您需要的(在./script计算其结束时浏览输出的开头),您可能需要使用临时文件:

 ./script >x & less x ; rm x

如果脚本在标准输出中写入数据,但在执行过程中出现段错误,那该怎么办呢?段错误可能会阻止缓冲输出被写入文件x。这是因为默认情况下,对文件的输出是块缓冲而不是行缓冲。我能否在脚本外部强制进行行缓冲?是否有一个现成的伪终端实用程序可供使用? - Rohit Banga

2
操作系统层面的管道已经满了,所以script会一直等待,直到less消耗掉部分内容。

如果你让你的脚本在输出文本时将内容写入日志文件,这似乎很容易进行测试。 - ninjagecko

2

流程控制。当less在分页时,您的脚本会被有效地暂停。

如果您想确保在交互使用less之前命令完成,请将less作为less +G调用,并且它将读取输入的末尾,然后您可以通过在less中键入1G返回到开头。


2

0
Can I externally enforce line buffering on the script? 
Is there an off the shelf pseudo tty utility I could use? 

您可以尝试使用script命令来打开行缓冲输出模式。
script -q /dev/null ./script | less      # FreeBSD, Mac OS X
script -c "./script" /dev/null | less    # Linux

如需更多相关的替代方案,请参见:关闭管道缓冲


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接