如何将系统日志日期时间 [UTC] 转换为纪元?

如何将系统日志日期时间 [UTC] 转换为纪元?

我目前正在拼凑一个工具来处理网络中生成的系统日志,其中一个要求是将日期时间从系统日志中的格式(%b %d %Y %T)转换为纪元。本质上,这就是我想要实现的目标:

原始系统日志格式:

1:      Jul 02 2019 15:14:19: %ASA-6-106015: <message> 
2:      Jul 02 2019 15:14:49: %ASA-6-106015: <message>

最终日志:

1:      1562080489   %ASA-6-106015  <message>
2:      1562080529   %ASA-6-106015  <message>

我知道我可以通过迭代整个日志并执行 date -d 操作来做到这一点。这是我想避免的事情。我更喜欢使用 GAWK 时间函数。

这是我的方法,

gawk -F: '{ print strftime("%s", timestamp}' syslog.log  

但这里的时间戳必须与 systime() 函数返回的值格式相同。但事实并非如此。

另外,我无法使用 mktime() 函数将 syslog 时间戳转换为所需的格式,因为它仅接受特定格式的输入 [YYYY MM DD HH MM SS]

我觉得有一种方法可以做到这一点,但我缺少它。任何替代方法也将受到赞赏。

答案1

使用 GNU date,您可以运行date一次并让它从标准输入获取输入。使用gawk 的协进程功能每个都有一个实例awkdate处理所有日期:

% awk -v cmd='stdbuf -oL date +%s -f-' -F': ' 'BEGIN{OFS=FS} {print $2 |& cmd; cmd |& getline $2} 1' foo
1: 1562048059: %ASA-6-106015: <message>
2: 1562048089: %ASA-6-106015: <message>

注意date的输出需要不缓冲(因此stdbuf -oL),否则协进程将挂起。

答案2

就像该date(1)实用程序一样,gawksmktime()假设日期规范使用当地时间。

要强制它使用UTCTZ应使用 envvar:

$ TZ=UTC gawk -F'[: ]+' '{sub(/([^:]+:){4} */, mktime(sprintf("%s %02d %s %d %d %d", $3, index("  JanFebMarAprMayJunJulAugSepOctNovDec",$1)/3, $2, $4, $5, $6))"\t"$7"\t"); print}'
1562080459      %ASA-6-106015   <message>
1562080489      %ASA-6-106015   <message>

答案3

以下是使用关联数组将月份名称转换为数字的典型方法,其中索引是月份名称,值是月份编号。例如mon["Jul"]是 7。这是在 BEGIN 块中设置一次。

awk 'BEGIN { 
       split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",months," ")
       for(i=1;i<=12;i++)mon[months[i]] = i }
     { m = $2; d = $3; y = $4; t = $5; gsub(":"," ",t)
       print mktime(y " " mon[m] " " d " " t) }'

然后,对于每一行,各个字段被重新排列成正确的顺序,mktime()并与中间的空格连接起来。时间t字段已:转换为空间字段。上面只是打印纪元时间,您仍然需要添加其余数据。

答案4

也许是珀尔:

perl -MTime::Piece -i.bak -pe '
    if ( /([[:upper:]][[:lower:]]{2} \d{2} \d{4} \d\d:\d\d:\d\d)/ ) {
        $datetime = Time::Piece->strptime($1, "%b %d %Y %T");
        $epoch = $datetime->epoch;
        s/$timestamp/$epoch/
    }
' log_file

相关内容