web-dev-qa-db-ja.com

pythonでプロセスの開始時刻(または稼働時間)を取得する方法

Linuxのpython)でプロセスの開始時間(または稼働時間)を取得する方法は?

私が知っているのは、 "ps -p my_process_id -f"を呼び出して、出力を解析することだけです。しかし、それはクールではありません。

34
stanleyxu2005

測定しようとしている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にアクセスするしかありません。経過時間を取得する素敵なbashyの方法は次のとおりです。

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

これは経過時間を次の形式で出力するだけなので、解析は非常に簡単です。

days-HH:MM:SS

(1日未満実行されている場合は、HH:MM:SSになります)

開始時間は次のように利用できます:

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

残念ながら、プロセスが開始しなかった場合todayを指定すると、時間ではなく、プロセスが開始した日付のみが表示されます。

これを行う最良の方法は、経過時間と現在の時間を取得して、ちょっとした計算を行うことです。以下はpythonスクリプトで、引数として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")
17
Daniel G

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だけでなく、クロスプラットフォームです。

注意:私はこのプロジェクトの作者の一人です。

57

man proc は、/proc/my_process_id/statは:

starttime %lu

時間は、システムのブート後に開始されたプロセスをjiffiesします。

ここでの問題は、Jiffyの長さを判別する方法と、システムがいつ起動したかを判別する方法です。

後者の答えは依然としてman proc: 入った /proc/stat、次のような独自の行:

btime 1270710844

これは、エポック以降の秒単位の測定です。


前者の答えはよくわかりません。 man 7 time さんのコメント:

ソフトウェアクロック、HZ、およびJiffies

多くのシステムコールとタイムスタンプの精度は、ソフトウェアクロックの分解能によって制限されます。ソフトウェアクロックは、時間をjiffy単位で測定するカーネルによって維持されるクロックです。 Jiffyのサイズは、カーネル定数HZの値によって決まります。HZの値は、カーネルのバージョンとハードウェアプラットフォーム。 x86での状況は次のとおりです。2.4.xまでのカーネルでは、HZは100で、Jiffy値は0.01秒でした。 2.6.0から、HZは1000に引き上げられ、0.001秒のJiffyが得られました。カーネル2.6.13以降、HZ値はカーネル構成パラメーターであり、100、250(デフォルト)、または1000にすることができ、それぞれ0.01、0.004、または0.001秒のjiffies値を生成します。

HZを見つける必要がありますが、Pythonからの値が250であることを期待していることを除いて、どうやってそれを処理するのかわかりません(Wikipediaがデフォルトであるため) 。

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

これは、Python :)の非常に小さなCモジュールでうまくやったように聞こえます

14
badp

Badpの回答に基づくコードは次のとおりです。

import os
from time import time

HZ = os.sysconf(os.sysconf_names['SC_CLK_TCK'])

def proc_age_secs():
    system_stats = open('/proc/stat').readlines()
    process_stats = open('/proc/self/stat').read().split()
    for line in system_stats:
        if line.startswith('btime'):
            boot_timestamp = int(line.split()[1])
    age_from_boot_jiffies = int(process_stats[21])
    age_from_boot_timestamp = age_from_boot_jiffies / HZ
    age_timestamp = boot_timestamp + age_from_boot_timestamp
    return time() - age_timestamp

それが正しいかどうかはわかりません。私は、sleep(5)を呼び出してそれを実行するテストプログラムを作成しました。出力は間違っており、実行ごとに数秒で変化します。これはvmwareワークステーションvmにあります:

if __name__ == '__main__':
    from time import sleep
    sleep(5)
    print proc_age_secs()

出力は次のとおりです。

$ time python test.py
6.19169998169

real    0m5.063s
user    0m0.020s
sys     0m0.036s
5
Dan Benamy
def proc_starttime(pid=os.getpid()):
    # https://Gist.github.com/westhood/1073585
    p = re.compile(r"^btime (\d+)$", re.MULTILINE)
    with open("/proc/stat") as f:
        m = p.search(f.read())
    btime = int(m.groups()[0])

    clk_tck = os.sysconf(os.sysconf_names["SC_CLK_TCK"])
    with open("/proc/%d/stat" % pid) as f:
        stime = int(f.read().split()[21]) / clk_tck

    return datetime.fromtimestamp(btime + stime)
2
Wilfred Hughes

解析できます/proc/uptime

>>> uptime, idletime = [float(f) for f in open("/proc/uptime").read().split()]
>>> print uptime
29708.1
>>> print idletime
26484.45

windowsマシンでは、おそらく wmi を使用できます

import wmi
c = wmi.WMI()
secs_up = int([uptime.SystemUpTime for uptime in c.Win32_PerfFormattedData_PerfOS_System()][0])
hours_up = secs_up / 3600
print hours_up
1
ghostdog74