如何在Python中获取进程启动时间(或运行时间)

41 投票
7 回答
58412 浏览
提问于 2025-04-15 21:22

如何在Linux中用Python获取进程的启动时间(或运行时间)?

我只知道可以用“ps -p my_process_id -f”这个命令,然后解析输出结果。但这样做不太方便。

7 个回答

17

man proc 里提到,在 /proc/my_process_id/stat 文件中,第22项是:

starttime %lu

这个值表示进程在系统启动后开始运行的时间,单位是“jiffies”。

现在你面临的问题是,如何确定一个“jiffy”的长度,以及如何知道系统是什么时候启动的。

关于后者的答案可以在 man proc 中找到:它在 /proc/stat 文件里,有一行类似这样的内容:

btime 1270710844

这个值是从“纪元”(Epoch)开始的秒数。


至于前者,我不太确定。man 7 time 里说:

软件时钟、HZ 和 Jiffies

很多系统调用和时间戳的准确性受到软件时钟分辨率的限制,这个时钟由内核维护,以“jiffies”为单位来计时。一个“jiffy”的大小由内核常量 HZ 的值决定。 HZ 的值在不同的内核版本和硬件平台上是不同的。在 x86 平台上,情况如下:在 2.4.x 及之前的内核中,HZ 是 100,这样一个“jiffy”的值是 0.01 秒;从 2.6.0 开始,HZ 提高到 1000,一个“jiffy”变成 0.001 秒;自 2.6.13 版本起,HZ 的值可以通过内核配置参数来设置,可以是 100、250(默认值)或 1000,分别对应的“jiffy”值是 0.01、0.004 或 0.001 秒。

我们需要找到 HZ 的值,但我不知道怎么在 Python 中做到这一点,只能希望它是 250(就像维基百科所说的默认值)。

ps 是这样获取这个值的:

  /* sysinfo.c init_libproc() */
  if(linux_version_code > LINUX_VERSION(2, 4, 0)){ 
    Hertz = find_elf_note(AT_CLKTCK);
    //error handling
  }
  old_Hertz_hack(); //ugh

这听起来像是一个非常小的 C 模块为 Python 完成的工作 :)

80

通过使用 psutil 这个库,你可以在这里找到它:https://github.com/giampaolo/psutil

>>> import psutil, os, time
>>> p = psutil.Process(os.getpid())
>>> p.create_time()
1293678383.0799999
>>> time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(p.create_time()))
'2010-12-30 04:06:23'
>>>

...而且它是跨平台的,不仅仅支持 Linux。

注意:我是这个项目的作者之一。

27

如果你是在你想要测量的 Python 程序内部进行操作,你可以这样做:

import time
# at the beginning of the script
startTime = time.time()
# ...
def getUptime():
    """
    Returns the number of seconds since the program started.
    """
    # do return startTime if you just want the process start time
    return time.time() - startTime

否则,你就只能解析 ps 命令的输出,或者查看 /proc/pid 目录。用 bash 的方式获取运行时间的方法是:

ps -eo pid,etime | grep $YOUR_PID | awk '{print $2}'

这个方法只会以特定的格式打印出运行时间,所以解析起来应该很简单:

days-HH:MM:SS

(如果运行时间少于一天,它的格式就是 HH:MM:SS

你可以这样获取开始时间:

ps -eo pid,stime | grep $YOUR_PID | awk '{print $2}'

不幸的是,如果你的进程不是今天启动的,这样做只会给你启动的日期,而不是具体时间。

最好的方法是获取运行时间和当前时间,然后做一些简单的数学运算。下面是一个 Python 脚本,它接受一个进程 ID(PID)作为参数,并为你完成上述操作,打印出进程的开始日期和时间:

import sys
import datetime
import time
import subprocess

# call like this: python startTime.py $PID

pid = sys.argv[1]
proc = subprocess.Popen(['ps','-eo','pid,etime'], stdout=subprocess.PIPE)
# get data from stdout
proc.wait()
results = proc.stdout.readlines()
# parse data (should only be one)
for result in results:
    try:
        result.strip()
        if result.split()[0] == pid:
            pidInfo = result.split()[1]
            # stop after the first one we find
            break
    except IndexError:
        pass # ignore it
else:
    # didn't find one
    print "Process PID", pid, "doesn't seem to exist!"
    sys.exit(0)
pidInfo = [result.split()[1] for result in results
           if result.split()[0] == pid][0]
pidInfo = pidInfo.partition("-")
if pidInfo[1] == '-':
    # there is a day
    days = int(pidInfo[0])
    rest = pidInfo[2].split(":")
    hours = int(rest[0])
    minutes = int(rest[1])
    seconds = int(rest[2])
else:
    days = 0
    rest = pidInfo[0].split(":")
    if len(rest) == 3:
        hours = int(rest[0])
        minutes = int(rest[1])
        seconds = int(rest[2])
    elif len(rest) == 2:
        hours = 0
        minutes = int(rest[0])
        seconds = int(rest[1])
    else:
        hours = 0
        minutes = 0
        seconds = int(rest[0])

# get the start time
secondsSinceStart = days*24*3600 + hours*3600 + minutes*60 + seconds
# unix time (in seconds) of start
startTime = time.time() - secondsSinceStart
# final result
print "Process started on",
print datetime.datetime.fromtimestamp(startTime).strftime("%a %b %d at %I:%M:%S %p")

撰写回答