web-dev-qa-db-fra.com

Comment récupérer l'heure de début du processus (ou disponibilité) en python

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. 

30
stanleyxu2005

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 bashy 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")
14
Daniel G

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.

48
Giampaolo Rodolà

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 de HZ 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 valeur HZ 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 :)

14
badp

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
4
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

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
0
ghostdog74