Como iniciar ou eliminar tarefas quando as temperaturas do núcleo ficam acima / abaixo de um valor específico?

1

Gostaria de escrever um pequeno script que seja iniciado manualmente uma vez e, em seguida, deve:

  • execute um comando se as temperaturas all estiverem abaixo de x ° C.
  • pause o comando se qualquer temperatura subir acima de y ° C.
  • continue o comando assim que todas as temperaturas caiam abaixo de x ° C novamente.

Claro que é x°C < y°C .

Eu posso obter os valores de temperatura, e. através do comando sensors :

$ sensors | grep °C
temp1:        +68.0°C  (crit = +95.0°C)
Core 0:       +68.0°C  (high = +80.0°C, crit = +90.0°C)
Core 2:       +67.0°C  (high = +80.0°C, crit = +90.0°C)

O script deve ser terminável o tempo todo, por exemplo através de killall scriptname . Se isso não funcionar com sua solução (por exemplo, porque ela registrará quaisquer eventos programados para pesquisar a temperatura), preciso de um comando separado para sair dela.

Como posso escrever este script?

    
por Byte Commander 19.01.2016 / 16:27

3 respostas

2

Esse script afetará toda a árvore de processos com raiz no processo executado.

Você pode facilmente testá-lo, executando-o em um terminal e verificando as temperaturas em outro terminal usando watch -n 1 'sensors -u | grep -Po "^ temp[0-9]+_input: \K.*"' .

Neste exemplo, os limites são definidos como 50 e 75 e a execução do processo é stress -c 3 : eles são codificados no script, mas é fácil modificar o script para lê-los a partir dos argumentos. / p>

Assim que todas as temperaturas estiverem abaixo de 50 ° C stress será iniciado; contanto que todas as temperaturas permaneçam abaixo de 75 ° C stress continuará; assim que uma temperatura estiver acima de 75 ° C, ostress irá parar; assim que todas as temperaturas estiverem abaixo de 50 ° C, novamente stress continuará novamente:

#!/bin/bash
function n_t_exceeding {
    sensors -u | awk -v x=0 -v temp=$1 '$1~/^temp[0-9]+_input:/{if($2 > temp){x++}}END{print x}'
}
set -m # Enables job control
mintemp=50 # First threshold
maxtemp=75 # Second threshold
while true; do
    if [ $(n_t_exceeding $mintemp) -eq 0 ]; then
        stress -c 3 & pid=$! # Starts the process, backgrounds it and stores the process' PID
        printf 'Started\n'
        break
    fi
    sleep 1 & wait $!
done
trap 'pkill -g $pid; exit' 2 # Upon SIGINT, sends SIGTERM to the process group and exits
while true; do
    if [ $(n_t_exceeding $maxtemp) -gt 0 ]; then
        pkill -19 -g $pid # Sends SIGSTOP to the process group
        printf 'Stopped\n'
        while true; do
            if [ $(n_t_exceeding $mintemp) -eq 0 ]; then
                pkill -18 -g $pid # Sends SIGCONT to the process group
                printf 'Resumed\n'
                break
            fi
            sleep 1 & wait $!
        done
    fi
    sleep 1 & wait $!
done
  • function n_t_exceeding { sensors -u | awk -v x=0 -v temp=$1 '$1~/^temp[0-9]+_input:/{if($2 > temp){x++}}END{print x}'; } analisa a saída de sensors -u e imprime o número de temperaturas acima de $1 (que é o primeiro argumento passado para a função):

    % sensors -u
    acpitz-virtual-0
    Adapter: Virtual device
    temp1:
      temp1_input: 45.000
      temp1_crit: 108.000
    
    asus-isa-0000
    Adapter: ISA adapter
    cpu_fan:
      fan1_input: 2200.000
    temp1:
      temp1_input: 45.000
    
    coretemp-isa-0000
    Adapter: ISA adapter
    Physical id 0:
      temp1_input: 47.000
      temp1_max: 87.000
      temp1_crit: 105.000
      temp1_crit_alarm: 0.000
    Core 0:
      temp2_input: 46.000
      temp2_max: 87.000
      temp2_crit: 105.000
      temp2_crit_alarm: 0.000
    Core 1:
      temp3_input: 47.000
      temp3_max: 87.000
      temp3_crit: 105.000
      temp3_crit_alarm: 0.000
    
    % sensors -u | awk -v x=0 -v temp=46 '$1~/^temp[0-9]+_input:/{if($2 > temp){x++}}END{print x}'
    2
    
  • set -m ativa o controle de tarefas;

  • mintemp=50; maxtemp=75 conjuntos $mintemp e $maxtemp a 50 e 75 respectivamente; estes são os limites 1) abaixo dos quais o processo deve começar na primeira vez e continuar novamente após ter excedido $maxtemp 2) acima do qual o processo deve parar;

  • trap 'pkill -g $pid; exit' 2 garante que o script terminará todos os processos no grupo de processos e sairá em CTRL + C ;

  • O primeiro loop while fica ocioso indefinidamente até o número de temperaturas acima de $mintemp ser 0 ; quando o número de temperaturas acima de $mintemp é 0 inicia o processo, coloca-o em segundo plano e interrompe o loop;

  • O segundo loop while fica ocioso indefinidamente até que o número de temperaturas acima de $maxtemp seja maior que 0 ; quando o número de temperaturas acima de $maxtemp for maior que 0 envia um SIGSTOP para o grupo de processos e inicia um terceiro while loop; o terceiro loop while fica ocioso indefinidamente até que o número de temperaturas acima de $mintemp seja 0 ; quando o número de temperaturas acima de $mintemp for 0 envia um SIGCONT para o grupo de processos e sai do loop.

por kos 19.01.2016 / 18:18
4

Isso pode funcionar:

#!/bin/bash

targettemp=90
started=1

COMMAND &

trap "kill COMMAND; exit" SIGINT SIGTERM

while true
do
  currenttemp=$(sensors -u | awk '/temp1_input/ {print $2; exit}' )
  compare=$(echo $currenttemp'>'$targettemp | bc -l)
  if [ "$compare" -eq 1 ] && [ "$started" -eq 1 ] 
  then
    started=0
    kill -STOP COMMAND
  fi
  if [ "$compare" -eq 0 ] && [ "$started" -eq 0 ]
  then
    started=1
    kill -CONT COMMAND
  fi
  sleep 1 & wait $!
done

Isto irá obter o resultado "temp1" atual dos sensores, cortar quaisquer outros caracteres que não sejam necessários para que o bash possa vê-lo como um número e, em seguida, compará-lo a qualquer temperatura-alvo definida por você. Meu raciocínio por trás de todo o acréscimo de "NR + 1000" e, em seguida, grep 1001 é porque você pode ter dois resultados "temp1" em sensors , como eu fiz. É meio chocante, mas funciona.

Então, quando você quiser matá-lo, apenas killall script.sh .

A linha sleep 1 serve para evitar o consumo excessivo de CPU devido à espera ocupada. Você pode mudar isso para qualquer sleep duration que você quiser se quiser pesquisar as temperaturas apenas de vez em quando.

    
por user323419 19.01.2016 / 17:05
2

O script

#!/usr/bin/env python3
import subprocess
import time
import sys

low = int(sys.argv[1]); high = int(sys.argv[2]); command = sys.argv[3:]; proc = command[0]

def get_temps():
    data = subprocess.check_output("sensors").decode("utf-8").splitlines()
    return sum([[float(l.split(":")[1].split()[0].replace("+", "").replace("°C", "")) \
        for l in data if l.startswith(mark)]for mark in ["temp1", "Core"]], [])

def manage_start():
    try:
        pid = subprocess.check_output(["pgrep", proc]).decode("utf-8").strip()
        subprocess.Popen(["killall", "-s", "CONT", proc])
    except subprocess.CalledProcessError:
        subprocess.Popen(["/bin/bash", "-c", (" ").join(command)])

run = False

while True:
    time.sleep(1)
    if run == False:
        if all([n < low for n in get_temps()]):
            manage_start(); run = True  
    elif run == True:
        if not all([n < high for n in get_temps()]):
            subprocess.Popen(["killall", "-s", "STOP", proc]); run = False

Como usar

  1. Copie o script em um arquivo vazio, salve-o como temp_run.py
  2. Execute-o, melhor antes que o processo é executado (o script iniciará o processo), com (subseqüentemente) o low_temp , o high_temp , o process_name e possível argumentos , como argumentos. Eu testei por exemplo com:

    python3 /path/to/temp_run.py 60 80 gedit /path/to/file.txt
    

    (usando outro editor de texto simples para alterar os números)

Como eu testei

Como não tenho a variedade na temperatura real , no script, substituí a função get_temps() por uma função, lendo números de um arquivo de texto.

Assim, "alimentando" o script com temperaturas virtuais, ele fez o trabalho sem um erro: pausa acima de "alto" ao executar, continuando abaixo de "baixo" quando pausado.

Como funciona

Quando o script começa

  • verifica se todas as temperaturas estão abaixo do limite mínimo.
  • Em caso afirmativo, ele inicia o processo ou o retoma, se já for executado, e define a variável: run = True
  • Como resultado, o próximo teste é se todos os temporários estiverem abaixo do limite mais alto, se o processo estiver pausado, o script definirá: run = False , fazendo o próximo teste se todos os temporários estiverem abaixo do mais baixo em ...

Como matar

O script pode ser eliminado por:

kill "$(pgrep -f temp_run.py)"
    
por Jacob Vlijm 19.01.2016 / 22:30