如何通过shell为流数据中的每一行添加时间戳?
off999 2024-10-31 14:06 23 浏览 0 评论
我希望每个文章通过一个简单小问题,来引导大家逐步深入了解学习shell,潜移默化的掌握shell编程的最佳实践。本文通过引入一个小问题以及解决方案来引导我们学习更多的shell命令行下时间的管理策略,以及了解这种管理方式在不同shell间的差异。
问题描述
在流中添加时间戳是一个挑战,因为没有标准工具可以完成这个任务。你可以安装针对此目的专门设计的工具(例如 moreutils 中的 ts,或者 daemontools 中的 multilog),或者使用某种编程语言编写过滤器。理想情况下,你不希望为每一行输入日志都创建一个 date(1) 命令的进程,因为这样太慢了。你应该使用内置工具。旧版本的 Bash 无法完成这个任务。你至少需要 Bash 4.2 版本才能使用 printf %(...)T 选项。否则,你可以使用 Perl、Python、Tcl 等编写程序来读取行并带有时间戳写出。
来尝试解决这个问题
在选择程序或编写函数(我们称之为 stamper)之后,你只需要将流通过它进行管道传输:
./myprogram 2>&1 | stamper > logfile
下面是一个简单的使用 Bash 4.2 的时间戳生成程序,以秒为单位进行精确度:
# Bash 4.2 or later
stamper() {
while read -r; do
printf '%(%Y-%m-%d %H:%M:%S)T %s\n' -1 "$REPLY"
done
}
在支持 strftime(3) 中的 %s 的系统上,你还可以使用 %(%s)T 来生成 Unix 时间戳。但遗憾的是,这种方法不是可移植的。
Bash 5.0 添加了 EPOCHSECONDS(1 秒精度)和 EPOCHREALTIME(微秒精度)变量,可以替代(或与之一同使用)printf %()T:
# Bash 5.0 or later
stamper() {
while read -r; do
printf '%s %s\n' "$EPOCHREALTIME" "$REPLY"
done
}
还有一个专门为此目的设计的外部工具是 moreutils 包中的 ts。它的默认格式选择不当(采用人类可读的月份名称,以 Mmm DD YYYY 格式显示),但你可以指定一个格式。它支持微秒精度。
stamper() {
ts "%Y-%m-%d %H:%M:%S.%.S"
}
另一个选择是 multilog,它可以提供纳秒级精度:
stamper() {
multilog t e 2>&1
}
multilog 的 -e 选项告诉它将每一行写入 stderr,而不是自动轮转目录中的文件。multilog 使用 TAI64N 格式写入时间戳,类似于 Unix epoch 格式。你可以使用转换工具(例如 tai64nlocal)将其转换为可读格式。
以下是使用 Tcl 的示例,精度为微秒:
#!/usr/bin/env tclsh
while {[gets stdin line] >= 0} {
set now [clock microseconds]
set frac [expr {$now % 1000000}]
set now [expr {$now / 1000000}]
puts "[clock format $now -format {%Y-%m-%d %H:%M:%S}].$frac $line"
}
这最好作为一个单独的、独立的脚本来使用。把它嵌入到bash函数中也是可以的,尽管很难看:
stamper() {
tclsh <(cat <<\EOF
while {[gets stdin line] >= 0} {
set now [clock microseconds]
set frac [expr {$now % 1000000}]
set now [expr {$now / 1000000}]
puts "[clock format $now -format {%Y-%m-%d %H:%M:%S}].$frac $line"
}
EOF
)
}
对于 Perl 爱好者,以下是一个精度为1秒的示例:
stamper() {
perl -p -e '$|=1; @l=localtime; printf "%04d-%02d-%02d %02d:%02d:%02d ",
1900+$l[5], $l[4], $l[3], $l[2], $l[1], $l[0]'
}
从上述选择中选择一个,或者用你喜欢的编程语言编写另一个(或更好的)。
现在,在这一点上,一些读者可能要问如何在记录带有时间戳的流到文件的同时查看未修改的流。假设他们不完全疯狂,所以他们不关心 stdout 和 stderr 的分离。他们只想要将所有内容按照顺序混合在一个文件中,包括 stdout 和 stderr。
现在,运行脚本使其输出和 stderr 正常显示到屏幕,将带有时间戳的行写入日志文件相对容易:
./myscript 2>&1 | tee >(stamper >logfile)
将同样的内容放入一个脚本中稍微复杂一些:
#!/bin/bash
exec > >(tee >(stamper >logfile)) 2>&1
while sleep 0.2s; do
echo "TPS report $RANDOM"
done
当然,如果脚本中写入 stamper 的部分使用 stdout 缓冲区,可能会存在缓冲问题。请考虑这一点。
我不在乎速度有多慢!我希望每秒调用 date(1) 一千次!我的电脑可以当作加热器使用!
这是低效和可怕的。
stamper() {
while read -r; do
printf '%s %s\n' "$(date +'%Y-%m-%d %H:%M:%S')" "$REPLY"
done
}
PS:请不要使用这种方法。这是愚蠢的。
More
如果你想学习如何编写更加健壮和可靠的 Shell 脚本,减少生产环境中的错误和故障,那么关注我吧!我会分享 Shell 编程的最佳实践和建议,帮助你提高 Shell 脚本的鲁棒性和可维护性。如果你想深入了解 Shell 编程的实际应用和技巧,可以关注我的《Shell 脚本编程最佳实践》专栏,里面有我在一线互联网大厂的实际生产经验和最佳实践,帮助你高效完成各种自动化任务。
相关推荐
- 推荐一款Python的GUI可视化工具(python 可视化工具)
-
在Python基础语法学习完成后,进一步开发应用界面时,就需要涉及到GUI了,GUI全称是图形用户界面(GraphicalUserInterface,又称图形用户接口),采用图形方式显示的计算机操...
- 教你用Python绘制谷歌浏览器的3种图标
-
前两天在浏览matplotlib官方网站时,笔者无意中看到一个挺有意思的图片,就是用matplotlib制作的火狐浏览器的logo,也就是下面这个东东(网页地址是https://matplotlib....
- 小白学Python笔记:第二章 Python安装
-
Windows操作系统的python安装:Python提供Windows、Linux/UNIX、macOS及其他操作系统的安装包版本,结合自己的使用情况,此处仅记录windows操作系统的python...
- Python程序开发之简单小程序实例(9)利用Canvas绘制图形和文字
-
Python程序开发之简单小程序实例(9)利用Canvas绘制图形和文字一、项目功能利用Tkinter组件中的Canvas绘制图形和文字。二、项目分析要在窗体中绘制图形和文字,需先导入Tkinter组...
- 一文吃透Python虚拟环境(python虚拟环境安装和配置)
-
摘要在Python开发中,虚拟环境是一种重要的工具,用于隔离不同项目的依赖关系和环境配置。本文将基于windows平台介绍四种常用的Python虚拟环境创建工具:venv、virtualenv、pip...
- 小白也可以玩的Python爬虫库,收藏一下
-
最近,微软开源了一个项目叫「playwright-python」,作为一个兴起项目,出现后受到了大家热烈的欢迎,那它到底是什么样的存在呢?今天为你介绍一下这个传说中的小白神器。Playwright是...
- python环境安装+配置教程(python安装后怎么配置环境变量)
-
安装python双击以下软件:弹出一下窗口需选择一些特定的选项默认选项不需要更改,点击next勾选以上选项,点击install进度条安装完毕即可。到以下界面,证明安装成功。接下来安装库文件返回电脑桌面...
- colorama,一个超好用的 Python 库!
-
大家好,今天为大家分享一个超好用的Python库-colorama。Github地址:https://github.com/tartley/coloramaPythoncolorama库是一...
- python制作仪表盘图(python绘制仪表盘)
-
今天教大家用pyecharts画仪表盘仪表盘(Gauge)是一种拟物化的图表,刻度表示度量,指针表示维度,指针角度表示数值。仪表盘图表就像汽车的速度表一样,有一个圆形的表盘及相应的刻度,有一个指针...
- 总结90条写Python程序的建议(python写作)
-
1.首先 建议1、理解Pythonic概念—-详见Python中的《Python之禅》 建议2、编写Pythonic代码 (1)避免不规范代码,比如只用大小写区分变量、使用容易...
- [oeasy]python0137_相加运算_python之禅_import_this_显式转化
-
变量类型相加运算回忆上次内容上次讲了是从键盘输入变量input函数可以有提示字符串需要有具体的变量接收输入的字符串输入单个变量没有问题但是输入两个变量之后一相加就非常离谱添加图片注释,不超过1...
- Python入门学习记录之一:变量(python中变量的规则)
-
写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...
- 掌握Python的"魔法":特殊方法与属性完全指南
-
在Python的世界里,以双下划线开头和结尾的"魔法成员"(如__init__、__str__)是面向对象编程的核心。它们赋予开发者定制类行为的超能力,让自定义对象像内置类型一样优雅工...
- 11个Python技巧 不Pythonic 实用大于纯粹
-
虽然Python有一套强大的设计哲学(体现在“Python之禅”中),但总有一些情况需要我们“打破规则”来解决特定问题。这触及了Python哲学中一个非常核心的理念:“实用主义胜于纯粹主义”...
- Python 从入门到精通 第三课 诗意的Python之禅
-
导言:Python之禅,英文名是TheZenOfPython。最早由TimPeters在Python邮件列表中发表,它包含了影响Python编程语言设计的20条软件编写原则。它作为复活节彩蛋...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python字典遍历 (54)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (60)
- python读取文件夹下所有文件 (59)
- java调用python脚本 (56)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)