risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come recuperare l'ora di inizio del processo (o tempo di attività) in python

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. 

30
stanleyxu2005

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

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.

48

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 di HZ 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 valore HZ è 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 :)

14
badp

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

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