我正在执行make all -d --trace
如何让Gnu Make输出每行的时间戳?
更一般地说,如何在每个STDOUT和STDERR语句中添加时间戳?
Linux/Bash有一个解决方案,但我在Windows上。
我创建了一个一行的批处理文件add_ts.bat
: echo %time% %1
我尝试了以下命令,但只得到了一个时间戳(没有输出的行):
make all --trace -d 2>&1 | add_ts.bat
我正在执行make all -d --trace
如何让Gnu Make输出每行的时间戳?
更一般地说,如何在每个STDOUT和STDERR语句中添加时间戳?
Linux/Bash有一个解决方案,但我在Windows上。
我创建了一个一行的批处理文件add_ts.bat
: echo %time% %1
我尝试了以下命令,但只得到了一个时间戳(没有输出的行):
make all --trace -d 2>&1 | add_ts.bat
大致上,您需要一个类似于批处理文件的东西:
add_ts.bat
@for /F "usebackq delims==" %%i in (`%1`) do @echo %time% %%i
你要运行的命令是:
add_ts.bat "make all -d --trace" > buildlog.txt
%1
的命令产生的STDOUT
以及STDERR
的时间戳,仅使用反引号操作符无法满足要求,因为此操作符仅捕获STDOUT
。STDERR
和STDOUT
,并使用重定向来实现。这意味着您需要运行一个子shell来理解重定向,同时需要转义重定向运算符,以防止它们被顶层shell解释。总的来说,需要执行以下操作:@for /F "usebackq delims==" %%i in (`cmd /C %1 2^>^&1`) do @echo %time% %%i
按同样的方式运行。
后来
我不明白的是,为什么|本身不足以将STDOUT和STDERR发送到add_ts.bat的STDIN
是的。我认为您存在两个误解的组合。
一:您认为程序的命令行参数与其标准输入相同,或者它从其标准输入获取命令行参数。它不是这样的。 如果有的话,程序的命令行参数将作为程序启动协议中的固定字符串列表传递给它。它的标准输入是一个输入流,由操作系统在程序启动时同时提供,并默认连接到控制台。可以通过重定向运算符在shell中覆盖此默认值。该输入流的内容事先并不固定。只要程序正在运行,并且程序读取它时,它将向程序提供控制台输入或其重定向代理输入的任何内容。程序可以解析或忽略其命令行参数,并且完全独立于此,它可以读取或忽略其标准输入。
你的程序add_ts.bat
是一个解析其命令行参数的程序,它使用 %1
并忽略其他所有输入。同时它完全忽略了标准输入。
第二点:你相信管道的效果,例如:a | b
目的是启动一个 a
进程,然后对于每一行写入标准输出,都会启动一个独立的 b
进程,并将由 a
写入的一行作为单个命令行参数(不管该行有多少个单词),自动发送给该进程并用其执行相应操作。
然而实际运行情况并非如此。操作系统只会启动一个 a
进程和一个 b
进程,并将前者的标准输出连接到后者的标准输入。为了使管道正常工作,b
必须是一个能够读取其标准输入的程序,而你的 add_ts.bat
并非如此。它只是一个解析其第一个命令行参数的程序:由于 |
不会提供任何参数,所以该命令行:
make all --trace -d 2>&1 | add_ts.bat
它也没有给出任何命令行。命令行:
make all --trace -d 2>&1 | add_ts.bat "Hello World"
会给它一个命令行参数并:
make all --trace -d 2>&1 | add_ts.bat Hello World
如果给它两个命令行参数,第二个将被忽略。但无论如何,它不会读取标准输入,因此对其进行管道处理是徒劳的。
网站ss64.com非常好地介绍了CMD
重定向和管道,但它假设您知道一个程序必须执行哪些操作才能成为可管道的命令:作为上游命令,它必须写入其标准输出;作为下游命令,它必须读取其标准输入。
如果您不介意额外的开销,使用批处理文件包装器是一个聪明的解决方案。否则,我认为您将不得不修改GNU make本身以使其打印出这些数据。
如果由于某种原因而无法接受上述方法,则可以使用ElectricMake获取该信息,它是一个GNU-make兼容的make实现,包括许多增强功能,包括带有每个构建作业微秒分辨率时间戳的注释构建日志。ElectricMake是ElectricAccelerator Huddle的一部分。
以下是一个微不足道的“echo Hello World!”作业的注释片段:
<job id="J00007fb820002000" thread="7fb82f7fe700" start="3" end="4" type="rule" name="all" file="
Makefile" line="1">
<command line="2">
<argv>echo Hello, world!</argv>
<output src="prog">Hello, world!
</output>
</command>
<commitTimes start="0.291693" wait="0.296587" commit="0.296628" write="0.296680"/>
<timing invoked="0.291403" completed="0.296544" node="ecdroid3a-59"/>
</job>
<timing>
标签显示了相对于构建开始时间的作业的开始时间(0.291403秒)和结束时间(0.296544秒)。
这些带注释的构建日志可以使用ElectricInsight进行图形查看和分析,这是ElectricMake的伴侣工具。
ElectricAccelerator Huddle是ElectricAccelerator的免费版本--在某个点之前完全免费使用,超出该点则需要支付适度的按需费用。
免责声明:我是ElectricAccelerator的架构师。
emake
能够正常工作,但是我的公司不想与之绑定,因为 ECloud 可能会随意将其变为非免费或者甚至停止支持。我和你们的销售代表谈过,他们说免费版本必须每三个月更新一次许可证。如果因为它正在侵蚀你们的企业销售而被停止支持怎么办?你能解决这些问题吗? - Bob
%1
替换为第一个命令行参数,以此类推,然后执行其逻辑并结束。将其输入进行管道传输并不能使其用第一整个STDIN
行替换%1
,然后为每个后续行重新运行自身。您的add_ts.bat
未传递任何命令行参数,并且没有读取其STDIN
的代码,无论是通过管道还是其他方式,因此它只打印了一次时间并停止了。 - Mike Kinghan|
本身不足以将STDOUT和STDERR发送到add_ts.bat
的STDIN。ss64.com对我理解如何/为什么有帮助吗? - Bob