Come recuperare l'ora di inizio del processo (o tempo di attività) in python in Linux?
So solo che posso chiamare "ps -p my_process_id -f" e quindi analizzare l'output. Ma non è bello.
Se lo stai facendo all'interno del programma python che stai cercando di misurare, potresti fare qualcosa del genere:
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
Altrimenti, non hai altra scelta che analizzare ps
o andare in /proc/pid
. Un buon modo bash
y per ottenere il tempo trascorso è:
ps -eo pid,etime | grep $YOUR_PID | awk '{print $2}'
Questo stamperà solo il tempo trascorso nel seguente formato, quindi dovrebbe essere abbastanza semplice da analizzare:
days-HH:MM:SS
(se è in esecuzione da meno di un giorno, è solo HH:MM:SS
)
L'ora di inizio è disponibile in questo modo:
ps -eo pid,stime | grep $YOUR_PID | awk '{print $2}'
Sfortunatamente, se il tuo processo non si avvia today , questo ti darà solo la data di inizio, piuttosto che il tempo.
Il modo migliore per farlo è quello di ottenere il tempo trascorso e l'ora corrente e basta fare un po 'di matematica. Quello che segue è uno script python che accetta un PID come argomento e lo fa per te, stampando la data e l'ora di inizio del processo:
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")
Utilizzando 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'
>>>
... in più è cross platform, non solo Linux.
NB: sono uno degli autori di questo progetto.
man proc
dice che il 22esimo elemento in /proc/my_process_id/stat
è:
starttime %lu
L'ora in jiffies è iniziata dopo l'avvio del sistema.
Il tuo problema ora è, come determinare la lunghezza di un Jiffy e come determinare quando il sistema viene avviato.
La risposta per quest'ultimo è ancora da man proc
: è in /proc/stat
, su una linea a sé stante in questo modo:
btime 1270710844
Questa è una misurazione in pochi secondi da Epoch.
La risposta per il primo non ne sono sicuro. man 7 time
dice:
Il software Clock, HZ e Jiffies
La precisione di molte chiamate di sistema e timestamp è limitata dalla risoluzione del clock del software, un clock gestito dal kernel che misura il tempo in jiffies. La dimensione di un Jiffy è determinata dal valore della costante del kernel
HZ
. Il valore diHZ
varia tra versioni del kernel e piattaforme hardware. Su x86 la situazione è la seguente: sui kernel fino al 2.4.x incluso,HZ
era 100, dando un valore Jiffy di 0,01 secondi; partendo da 2.6.0,HZ
è stato portato a 1000, dando un Jiffy di 0.001 secondi; dal kernel 2.6.13, il valoreHZ
è un parametro di configurazione del kernel e può essere 100, 250 (il valore predefinito) o 1000, ottenendo un valore di jiffies rispettivamente di 0,01, 0,004 o 0,001 secondi.
Abbiamo bisogno di trovare HZ
, ma non ho idea di come farei questo da Python eccetto per sperare che il valore sia 250 (come afferma Wikipedia come impostazione predefinita).
ps
lo ottiene così:
/* 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
Sembra un lavoro ben fatto da un modulo C molto piccolo per Python :)
Ecco il codice basato sulla risposta di 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
Non sono sicuro se sia giusto comunque. Ho scritto un programma di test che chiama sleep (5) e poi lo esegue e l'output è errato e varia in un paio di secondi dall'inizio alla fine. Questo è in un vmware workstation vm:
if __== '__main__':
from time import sleep
sleep(5)
print proc_age_secs()
L'output è:
$ time python test.py
6.19169998169
real 0m5.063s
user 0m0.020s
sys 0m0.036s
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)
puoi analizzare /proc/uptime
>>> uptime, idletime = [float(f) for f in open("/proc/uptime").read().split()]
>>> print uptime
29708.1
>>> print idletime
26484.45
per macchine Windows, puoi probabilmente usare 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