我正在尝试读取为构建生成的 /timestamps 文件,但我无法理解文件格式,因为当我尝试打开它时包含一些特殊字符。我想将此文件用于构建完成后将作为批处理命令运行的脚本。任何帮助,将不胜感激。谢谢
3 回答
像这样依赖插件的内部数据结构被认为是不好的做法。
建议您联系该插件的作者,看看他是否可以为此提供一些 API。
如果您使用的是时间戳插件https://plugins.jenkins.io/timestamper/
您可以使用插件的 API 读取日志。
http://${JENKINS_IP_PORT}/job/${JOB_NAME}/${JOB_NUMBER}/console
如果插件已启用,将返回带有时间戳的控制台视图,如果已禁用,将返回带有时间戳的控制台视图。
http://${JENKINS_IP_PORT}/job/${JOB_NAME}/${JOB_NUMBER}/consoleText
将以纯文本形式返回日志
时间戳插件 API
但是,当为作业启用插件时,您可以使用“脚本”部分下提供的API。响应是纯文本格式。
您可以将返回的时间戳格式化为日期、时间、日期+时间、经过时间(自作业开始以来的时间)等。
例子
http://${JENKINS_IP_PORT}/job/${JOB_NAME}/${JOB_NUMBER}/timestamps/?time=yyyy-MM-dd%20HH:mm:ss&appendLog
2020-03-19 13:16:47 Jenkins did something here
2020-03-19 13:16:47 and this is something else that happend
2020-03-19 13:16:47 This line shows some output
2020-03-19 13:16:47 etc.
2020-03-19 13:16:47 etc.
2020-03-19 13:16:47 ...
2020-03-19 13:16:47 ...
2020-03-19 13:16:47
2020-03-19 13:16:47
返回时间戳并附加日志。日期格式为“2020-03-19 16:30:23”
使用 M 而不是 MM 将返回没有前面 0 的月份。
使用 MMM 会将月份返回为 3 个字母的月份,例如“MAR”
http://${JENKINS_IP_PORT}/job/${JOB_NAME}/${JOB_NUMBER}/timestamps
2.667
2.670
2.768
32.778
32.778
32.820
将返回没有日志行的时间戳。自构建开始以来的秒数的简单纯文本列表。
http://${JENKINS_IP_PORT}/job/${JOB_NAME}/${JOB_NUMBER}/timestamps/?time=yyyy-MM-dd%20HH:mm:ss
2020-03-19 13:16:47
2020-03-19 13:16:47
2020-03-19 13:16:47
2020-03-19 13:16:47
2020-03-19 13:16:47
2020-03-19 13:16:47
2020-03-19 13:16:47
2020-03-19 13:16:47
2020-03-19 13:16:47
将返回格式化的时间戳列表
警告
Timestamper API 仅在作业启用插件时可用。在其他情况下访问 API url 将返回一个空响应。
六年后……我也有同样的问题,但找不到答案。所以我根据互联网上的花絮和我自己的实验拼凑出我自己的解决方案。
我正在编写一个 Web 脚本来生成实时报告,它需要带有时间戳的 Jenkins 日志。使用时间戳 URL/API 对我来说不是一个选项,因为我的网络服务器阻止了向其他网络服务器发送 HTTP 请求。所以我需要能够直接从时间戳文件中提取时间戳信息,该文件可通过磁盘安装在我的服务器上使用。
请注意,我正在使用带有时间戳 1.10 的 Jenkins 2.190.1。你的旅费可能会改变。
简要说明:
基本上,时间戳文件给出了日志之间经过的时间,以毫秒为单位。数据以 base-128 (varint) 格式列出。因此,您需要一次读取一个字节的文件。如果任一字节大于0x7F(127),则需要取最低7位,左移7位,然后读取下一个字节;重复直到读取的字节大于 0x7F。
详细解释(包括Perl代码):
例如,给定以下字节(从真实时间戳文件的开头读取):
08 01 2c 04 0c 04 25 01 04 02 00 02 fe 47 11 ...
第一个字节 0x08 小于 0x7f,因此第一个日志发生在构建开始后 8 毫秒。第二个字节 0x01 表示第二个日志发生在第一个日志之后 1ms。第三个日志发生在第二个日志之后 0x2C 毫秒(44 毫秒)。等等。
第 13 个日志(字节 0xfe)的情况略有不同。由于 0xfe > 0x7f,我们只需要最低的 7 位。
0xfe & 0x7f = 1111 1110 & 0111 1111 == 0111 1110 = 0x7e == 126
然后我们将结果左移 7 位(即乘以 128):
0x7e << 7 == 0x3f00 == 16128
然后我们读取下一个字节(0x47),它小于 0x7F,所以它是这个(第 13 个)日志的最后一个字节。所以我们只需将此值添加到上面的左移值:
0x3f00 + 0x47 = 0x3f47 = 16128 + 71 = 16199
所以第 13 条日志发生在第 12 条日志之后 16199 毫秒(或 16.199 秒)。
对时间戳文件中的每个字节重复此过程。
这给出了文件中每个日志之间经过的时间(以毫秒为单位)。要找到实际的纪元时间戳,请使用时间戳文件的最后修改时间,然后向后工作。然后以您想要的任何日期/时间格式显示每个日志的纪元时间。
Perl 代码示例:
以下 Perl 函数有效 (Perl 5.22)。它基于 [ https://github.com/danaj/BitStream/blob/master/lib/Data/BitStream/Code/Varint.pm][1]中的 get_varint() 函数,但 Varint.pm 模块不是t 在我的服务器上可用(让 IT 人员安装它实际上比我编写和测试以下代码花费的时间要长得多)。它可能不漂亮,但它有效。
我希望它有所帮助。
my @Timestamps = ();
my $path = "/full/path/to/timestamps";
if(open(TS, '<:raw', $path))
{
my($byte, $ok, $shift);
my $elapsed = 0;
my $ms = 0;
while()
{
$ok = read(TS, $byte, 1);
if(!defined($ok) || $ok <= 0)
{ last; }
$byte = sprintf("%d", ord($byte));
$shift = 7;
$ms = $byte & 0x7F;
while($byte > 127)
{
$ok = read(TS, $byte, 1);
if(!defined($ok) || $ok <= 0)
{ last; }
$byte = sprintf("%d", ord($byte));
$ms |= ($byte & 0x7F) << $shift;
$shift += 7;
} # end while byte
$elapsed += $ms;
push(@Timestamps, $elapsed);
} # end while
close(TS);
} # end if open