2012-05-02 29 views
5

Me gustaría obtener la temperatura de un disco duro usando Python (en Linux). Actualmente estoy llamando al hddtemp con subprocess.popen, pero lo llamo con la suficiente frecuencia que es un cuello de botella de rendimiento en mi secuencia de comandos. Creo que debería ser posible hacer algo similar al question 4193514?Obtener la temperatura del disco duro usando Python

+3

¿Con qué frecuencia está controlando la temperatura? Debería poder almacenar en caché el valor por un minuto más o menos. No cambia muy rápido. –

+4

@gnibbler: ¿Pero cómo sería capaz de medir la circunstancia de arrojar la máquina a una chimenea? – jdi

+0

Es para una página web que muestra el estado del servidor en tiempo real. Cuando la página está abierta, se actualiza cada 5-10 segundos. – lyineyes

Respuesta

5

Puede ejecutar hddtemp como un demonio (la opción -d), a continuación, utilizar sockets para consultar que - por defecto es el puerto 7634. ​​

Editar: ver some code that does this.

+0

Eso es exactamente lo que estaba buscando, ¡Gracias! Puntos de bonificación para el ejemplo de código. – lyineyes

2

Ampliando lo que @gnibbler sugirió en su comentario principal, ¿qué tal un enfoque en caché? Este es un ejemplo sencillo estúpidamente sólo para mostrar el concepto:

from collection import defaultdict 

class CachedValue(object): 
    def __init__(self): 
     self.timestamp = -1 
     self._value = None 

    @property 
    def value(self): 
     return self._value 

    @value.setter 
    def value(self, val): 
     self._value = val 
     self.timestamp = time.time() 

    def isOld(self, seconds): 
     return (time.time() - self.timestamp) >= seconds 

>>> _cached = defaultdict(CachedValue) 
>>> _cached['hddtemp'].isOld(10) 
True 
>>> _cached['hddtemp'].value = 'Foo' 
>>> _cached['hddtemp'].isOld(10) 
False 
# (wait 10 seconds) 
>>> _cached['hddtemp'].isOld(10) 
True 

Y en su caso específico:

def reportHDD(self): 
    if self._cached['hddtemp'].isOld(10): 
     self._cached['hddtemp'].value = self.getNewHDDValue() 
    return self._cached['hddtemp'].value 

Este enfoque es realmente más de una solución general para el almacenamiento en caché una operación costosa. En aplicaciones más grandes, CachedValue podría reemplazarse fácilmente con una simple búsqueda memcached/redis que mantenga su propio valor TTL por usted. Pero a pequeña escala, esta es solo una forma elegante de organizar los valores locales en caché.

+0

Gran ejemplo. Creo que usaré esto para las otras funciones, pero para obtener la temperatura del disco duro, he recurrido a engendrar un hilo (para tratar de mitigar la sobrecarga de la llamada lenta al sistema) para actualizar una entrada dic. – lyineyes

+0

@lyineyes: ¿Pero por qué incluso incurrir en gastos generales ya sea en un hilo o en cualquier otro lugar, si la temperatura solo puede fluctuar en un plazo razonable? Pero Hugh Bothwell menciona en su respuesta que solo puedes monitorear específicamente la versión daemonizada de esta herramienta. Entonces esa es probablemente tu solución más específica. ¡Pero me alegra que te haya gustado este enfoque para una solución de almacenamiento en caché general! – jdi

2

Estaba buscando en Google por un tiempo y este golpe siguió apareciendo cerca de la parte superior sin importar cómo formateé mi búsqueda. Tengo smartmontools y al menos Python 2.7.6 instalado en todos mis hosts y no quería instalar un nuevo paquete para canalizar los datos hdd temp a graphite/statsd así que hice lo siguiente.

No soy un desarrollador y no conozco Python (como obvio) así que este es mi intento de 1 a 2 días para resolverlo. Estoy demasiado avergonzado para publicar todo el código aquí, pero aquí está el dealy principal ::

enter code here 
#!/usr/bin/env python 
import os 

import subprocess 

import multiprocessing 

def grab_hdd_temp(hdd, queue): 
    for line in subprocess.Popen(['smartctl', '-a', str('/dev/' + hdd)], stdout=subprocess.PIPE).stdout.read().split('\n'): 
    if ('Temperature_Celsius' in line.split()) or ('Temperature_Internal' in line.split()): 
     queue.put([hdd, line.split()[9]]) 

def hddtmp_dict(hdds_list): 
    procs = [] 
    queue = multiprocessing.Queue() 
    hddict={} 
    for hdd in hdds_list: 
    p = multiprocessing.Process(target=grab_hdd_temp, args=(hdd, queue)) 
    procs.append(p) 
    p.start() 
    for _ in procs: 
    val = queue.get() 
    hddict[val[0]]=val[1] 
    p.join() 
    return hddict 

if __name__ == '__main__': 
    hdds_list = [ x for x in os.listdir('/sys/block/') if x.startswith('sd') ] 
    hddict = hddtmp_dict(hdds_list) 
    for k in hddict: 
     print(k, hddict[k]) 

En mi servidor de almacenamiento de este regresó la lista completa de 38 unidades en 2 segundos vs 50 segundos para recorrer toda la discos en serie. Eso dijo que la carga salta de alrededor de 1.08 a 3.50 en una caja de 40 núcleos. Así que tómalo como quieras. Estoy tratando de encontrar una forma de usar proc o posiblemente fcntl based on another stack overflow I found para extraer los datos en lugar de usar subprocess.popen pero eh.

aquí son las 2:22 a.m. y tengo que volver a casa. Una vez allí, trataré de delinear el fragmento de arriba y decir lo que creo que está haciendo todo, pero espero que sea algo que se explique por sí mismo.

Disculpa el código de kludge. Creo que el buffer es la mejor manera de ir en este punto, pero fue un ejercicio genial. Si no desea instalar hddtemp, creo que un buffer + de arriba puede ser la mejor opción. Todavía trato de resolver eso tan bien como que todavía no entiendo cómo hacer clases.

Espero que esto ayude a alguien.

+0

Lamentablemente, actualmente estoy suspendido de ServerFault por un año, porque aconsejé a los novatos que usen la tecla Mayús si comienzan una oración :-) – peterh

Cuestiones relacionadas