Я хотел бы записать короткий сценарий, который запускается вручную однажды, и затем должен:
x
°C.y
°C.x
°C снова.Конечно, это x°C < y°C
.
Я могу получить температурные значения, например, через 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)
Сценарий должен быть срочным все время, например, через killall scriptname
. Если это не будет работать с Вашим решением (например, потому что оно зарегистрирует любые запланированные события для опроса температуры), мне нужна отдельная команда для выхода из него.
Как я могу записать этот сценарий?
Этот сценарий будет влиять на целое дерево процесса, базированное при процессе, выполненном в нем.
Можно легко протестировать его путем выполнения его в терминале и проверки температур в другое терминальное использование watch -n 1 'sensors -u | grep -Po "^ temp[0-9]+_input: \K.*"'
.
В этом примере пороги устанавливаются к 50
и 75
и выполненный процесс stress -c 3
: они трудно кодируются в сценарий, но легко изменить сценарий для чтения их из аргументов.
Как только все температуры будут ниже 50°C stress
запустится; пока все температуры останутся ниже 75°C stress
продолжится; как только одна температура будет выше 75°C stress
остановится; как только все температуры будут ниже 50°C снова stress
продолжится снова:
#!/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}'; }
анализирует вывод sensors -u
и печатает количество температур выше $1
(который является первым аргументом, переданным функции):
% 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
включает управление заданиями;
mintemp=50; maxtemp=75
наборы $mintemp
и $maxtemp
кому: 50
и 75
соответственно; это пороги 1), ниже которых процесс должен запуститься в первый раз и продолжиться снова превысив $maxtemp
2) выше которого должен остановиться процесс;
trap 'pkill -g $pid; exit' 2
удостоверяется, что сценарий завершит все процессы в группе процесса и выходе на CTRL+C;
Первое while
цикл бездействует неограниченно долго до количества температур $mintemp
0
; когда количество температур $mintemp
0
запускает процесс, помещает его в фон и убегает из цикла;
Второе while
цикл бездействует неограниченно долго до количества температур $maxtemp
больше, чем 0
; когда количество температур $maxtemp
больше, чем 0
отправляет SIGSTOP группе процесса и запускает одну треть while
цикл; третье while
цикл бездействует неограниченно долго до количества температур $mintemp
0
; когда количество температур $mintemp
0
отправляет SIGCONT группе процесса и убегает из цикла.
Это могло бы работать:
#!/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
Это получит текущий результат "temp1" датчиков, обрезка любые другие символы, в которых это не нуждается так, чтобы удар видел его, поскольку число, затем сравните его с любой целевой температурой, которую Вы устанавливаете.
Мое обоснование позади целого добавления "NR+1000" и затем grep 1001
состоит в том, потому что у Вас могло бы быть два результата "temp1" в sensors
, как я сделал. Это - вид клуджа, но это работает.
Затем когда Вы хотите уничтожить его, всего killall script.sh
.
sleep 1
строка должна избежать избыточного потребления ресурсов ЦП от активного ожидания. Можно изменить это на любой sleep duration
, Вам нравится, если Вы хотите только опросить температуры время от времени.
#!/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
temp_run.py
Выполните его, лучше всего перед выполнениями процесса (сценарий запустит процесс), с (впоследствии) low_temp
, high_temp
, process_name
и возможные аргументы, как аргументы. Я протестировал его, например, с:
python3 /path/to/temp_run.py 60 80 gedit /path/to/file.txt
(использующий другого редактора простого текста для изменения числа)
Так как у меня нет разнообразия в реальной температуре в сценарии, я заменил функцию get_temps()
, функцией, читая числа из текстового файла.
Таким образом "подавая" сценарий с виртуальными температурами, это сделало задание без ошибки: приостановка выше "высокого" при выполнении, возобновлении ниже "низкого" при приостановке.
Когда сценарий запускается
run = True
run = False
, создание следующего теста, если все временные файлы ниже самого низкого и так далее...Сценарий может быть уничтожен:
kill "$(pgrep -f temp_run.py)"