Comment récupérer l'heure de début du processus (ou la disponibilité) en python sous Linux?
Je sais seulement que je peux appeler "ps -p my_process_id -f" et ensuite analyser la sortie. Mais ce n'est pas cool.
Si vous le faites depuis le programme python que vous essayez de mesurer, vous pourriez faire quelque chose comme ça:
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
Sinon, vous n'avez pas d'autre choix que d'analyser ps
ou d'aller dans /proc/pid
. Une belle manière bash
y de récupérer le temps écoulé est la suivante:
ps -eo pid,etime | grep $YOUR_PID | awk '{print $2}'
Cela imprimera seulement le temps écoulé dans le format suivant, il devrait donc être assez facile à analyser:
days-HH:MM:SS
(s'il fonctionne depuis moins d'un jour, il s'agit simplement de HH:MM:SS
)
L'heure de début est disponible comme ceci:
ps -eo pid,stime | grep $YOUR_PID | awk '{print $2}'
Malheureusement, si votre processus n'a pas démarré aujourd'hui , cela ne vous donnera que la date à laquelle il a commencé, plutôt que l'heure.
La meilleure façon de faire est d’obtenir le temps écoulé et l’heure actuelle et de faire un peu de calcul. Voici un script python qui prend un PID en tant qu'argument et fait ce qui précède pour vous, en affichant la date et l'heure de début du processus:
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")
En utilisant 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'
>>>
... plus c'est multi-plateforme, pas seulement Linux.
NB: Je suis l'un des auteurs de ce projet.
man proc
indique que le 22ème élément de /proc/my_process_id/stat
est:
starttime %lu
Le temps en jiffies le processus a démarré après le démarrage du système.
Votre problème est maintenant de savoir comment déterminer la longueur d’un Jiffy et comment déterminer quand le système a démarré.
La réponse pour ce dernier provient toujours de man proc
: c'est dans /proc/stat
, sur une ligne distincte comme celle-ci:
btime 1270710844
C'est une mesure en secondes depuis Epoch.
La réponse pour l'ancien je ne suis pas sûr. man 7 time
dit:
L'horloge logicielle, HZ et Jiffies
La précision de l’horloge logicielle, une horloge maintenue par le noyau qui mesure le temps en un tournemain, limite la précision de nombreux appels système et horodatages. La taille d'un Jiffy est déterminée par la valeur de la constante du noyau
HZ
. La valeur deHZ
varie selon les versions du noyau et les plates-formes matérielles. Sur x86, la situation est la suivante: sur les noyaux jusqu’à 2.4.x inclus,HZ
était égal à 100, ce qui donne une valeur Jiffy de 0,01 seconde; à partir de 2.6.0,HZ
a été augmenté à 1000, donnant un Jiffy de 0,001 seconde; Depuis le noyau 2.6.13, la valeurHZ
est un paramètre de configuration du noyau et peut être 100, 250 (valeur par défaut) ou 1000, donnant une valeur Jiffies de, respectivement, 0,01, 0,004 ou 0,001 seconde.
Nous devons trouver HZ
, mais je n'ai aucune idée de la façon dont je procéderais de la sorte en Python, si ce n'est que j'espère que la valeur est 250 (comme Wikipédia le prétend par défaut).
ps
l'obtient ainsi:
/* 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
Cela ressemble à un travail bien fait par un très petit module C pour Python :)
Voici le code basé sur la réponse de 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
Je ne sais pas si c'est vrai cependant. J'ai écrit un programme de test qui appelle sleep (5) puis l'exécute. La sortie est incorrecte et varie en quelques secondes entre deux exécutions. Ceci est dans un vmware workstation vm:
if __== '__main__':
from time import sleep
sleep(5)
print proc_age_secs()
La sortie est:
$ 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)
vous pouvez analyser /proc/uptime
>>> uptime, idletime = [float(f) for f in open("/proc/uptime").read().split()]
>>> print uptime
29708.1
>>> print idletime
26484.45
pour les machines Windows, vous pouvez probablement utiliser 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