公众号旧文

真正精确的运行时间看 ps 的 etime 最方便

作者:胖子阅读 —

#Linux

在 Linux 服务器运维中,我们经常需要判断一个进程到底运行了多久。

很多人第一反应会使用:

systemctl status 服务名

例如:

systemctl status china-exit-ip-scan.service

输出可能类似:

Active: activating (start) since Fri 2026-08-14 14:07:28 CST; 2 days ago

乍一看,我们很容易理解成:

这个服务运行了大约两天。

但这里有一个细节:systemctl status 后面的 2 days ago 是为了方便人阅读而显示的相对时间,它并不是一个适合精确计算运行时长的字段。

如果我们真正想知道:

这个进程到底已经连续运行了几天、几小时、几分钟?

那么更方便的方法,是直接查看 ps 的 etime。


一、systemctl status 的时间并不够精确

例如一个任务显示:

Active: activating (start) since Fri 2026-08-14 14:07:28 CST; 2 days ago

这里实际上同时包含了两种时间信息。

第一种是精确启动时间:

Fri 2026-08-14 14:07:28 CST

第二种是人类可读的相对时间:

2 days ago

问题就在第二部分。

2 days ago 只是一个粗粒度的描述。

例如一个任务已经运行:

48 小时
51 小时
60 小时
70 小时

都有可能在一段时间内显示成:

2 days ago

它不会告诉你:

2 天 3 小时 36 分

还是:

2 天 20 小时

所以如果只是快速判断服务是不是几天前启动的,systemctl status 很方便。

但如果需要精确判断运行时间,它就不够直观了。


二、直接使用 ps 查看 etime

Linux 的 ps 命令提供了一个非常实用的字段:

etime

它表示:

Elapsed Time,即进程从启动到现在经过的真实墙钟时间。

例如:

ps -p 1653274 -o pid,lstart,etime,time,cmd

输出:

PID      STARTED                      ELAPSED       TIME      CMD
1653274  Fri Aug 14 14:07:27 2026    2-03:36:03   10:49:31  python3 -u scanner-v6.py

这里最值得关注的是:

ELAPSED
2-03:36:03

它的格式是:

天-小时:分钟:秒

所以:

2-03:36:03

表示:

2 天
3 小时
36 分钟
3 秒

也就是:

这个 Python 进程已经连续运行了 51 小时 36 分 3 秒。

相比 systemctl status 的:

2 days ago

显然精确得多。


三、不要把 etime 和 time 搞混

ps 里还有另一个很容易混淆的字段:

time

例如:

ELAPSED       TIME
2-03:36:03    10:49:31

这两个数字含义完全不同。

etime

表示:

从进程启动到现在经过了多久

也就是实际现实世界中的时间。

例如:

2-03:36:03

表示程序启动已经超过两天。

time

表示:

进程累计实际使用了多少 CPU 时间

例如:

10:49:31

表示这个进程累计消耗了:

10 小时 49 分 31 秒 CPU 时间

所以一个程序完全可能出现:

ELAPSED = 51 小时
TIME    = 10 小时

这并不矛盾。

它说明剩余的大量时间可能花在:

  • 等待网络响应
  • 等待磁盘 I/O
  • 等待其他子进程
  • socket timeout
  • HTTP 请求
  • nmap 扫描
  • sleep
  • 系统调度

对于网络扫描程序来说,这种情况尤其常见。


四、lstart 可以直接看到准确启动时间

除了 etime,另一个非常实用的字段是:

lstart

例如:

ps -p 1653274 -o lstart

输出:

Fri Aug 14 14:07:27 2026

lstart 的意思是:

Long Start Time

也就是进程完整的启动日期和时间。

因此在排查长期运行任务时,可以把:

lstart
etime
time

三个字段一起看。

例如:

ps -p 1653274 -o pid,lstart,etime,time,cmd

一次就能知道:

什么时候启动
已经运行多久
用了多少 CPU
运行的是什么程序

五、为什么 systemctl show ActiveEnterTimestamp 有时是空的

有时候我们还会尝试:

systemctl show china-exit-ip-scan.service \
  -p ActiveEnterTimestamp \
  -p ActiveEnterTimestampMonotonic

结果却是:

ActiveEnterTimestamp=
ActiveEnterTimestampMonotonic=0

这并不一定代表 systemd 出问题了。

例如服务当前状态是:

Active: activating (start)

意味着这个 service 还处于启动过程中。

如果它对应的是一个长时间运行、执行完才退出的脚本,那么 systemd 可能一直认为:

activating

而还没有真正进入:

active

状态。

既然没有进入 active,自然也就不存在:

ActiveEnterTimestamp

这种情况下,直接查看真正执行任务的进程:

ps

反而更加直接。


六、长期任务最推荐的查看方式

对于扫描器、备份任务、同步任务、爬虫、大数据处理脚本这类可能运行数小时甚至数天的进程,我通常建议直接使用:

ps -p PID -o pid,lstart,etime,time,%cpu,%mem,cmd

例如:

ps -p 1653274 \
  -o pid,lstart,etime,time,%cpu,%mem,cmd

这样可以同时得到:

PID
启动时间
已经运行时间
累计 CPU 时间
CPU 占用
内存占用
完整命令

比单纯查看:

systemctl status

更适合分析一个长期任务到底发生了什么。


七、不知道 PID 时,可以自动查找

如果 PID 每次都会变化,也没必要手动先查 PID。

例如一个 Python 程序:

scanner-v6.py

可以直接:

pgrep -af scanner-v6.py

找到进程。

也可以组合成:

ps -p $(pgrep -f 'python3 -u scanner-v6.py' | head -1) \
  -o pid,lstart,etime,time,%cpu,%mem,cmd

以后只要执行这一条,就能快速看到当前扫描器的运行状态。


八、如何判断一个任务是不是“卡死”

etime 还有一个很实用的用途,就是帮助判断长期任务是否真的卡住。

假设:

ELAPSED
2-03:36:03

只能说明任务已经运行两天多。

它本身不能证明任务卡死。

还需要结合:

TIME

以及日志、子进程状态一起判断。

例如隔半小时查看两次:

第一次:

ELAPSED: 2-03:36:03
TIME:    10:49:31

第二次:

ELAPSED: 2-04:06:03
TIME:    11:03:42

说明:

墙钟时间增加 30 分钟
CPU 时间也增加了 14 分钟

这通常说明程序仍然在持续执行。

如果同时还能看到:

nmap ...

或者日志持续出现:

[SCAN]
[CHECK]
[FOUND]
[SKIP]

那么基本可以确认:

程序只是运行时间很长,并没有真正卡死。

反过来,如果连续几个小时:

etime 不断增加
CPU time 几乎不增加
日志完全没有新内容
没有任何子进程变化

这时候才值得进一步检查:

  • 网络请求是否无限等待
  • timeout 是否失效
  • subprocess 是否挂起
  • 文件锁
  • socket 阻塞
  • 死循环或死锁

九、运维中应该怎么选

简单来说,可以这样记:

想看服务整体状态
→ systemctl status

想看进程什么时候启动
→ ps 的 lstart

想看真正运行了多久
→ ps 的 etime

想看累计用了多少 CPU
→ ps 的 time

想看当前资源占用
→ %cpu / %mem

其中对于长期运行任务:

真正精确的运行时间,看 ps 的 etime 最方便。

例如:

ps -p PID -o pid,lstart,etime,time,cmd

这是一个非常简单,却非常实用的 Linux 运维习惯。

当一个任务已经运行几十个小时以后,与其盯着:

2 days ago

猜它究竟运行了多久,不如直接看:

2-03:36:03

数字会告诉你准确答案。