当核心温度高于/低于特定值时,如何启动或终止任务?

当核心温度高于/低于特定值时,如何启动或终止任务?

我想编写一个简短的脚本,手动启动一次,然后应该:

  • 如果全部气温低于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。如果这对您的解决方案不起作用(例如,因为它将注册任何计划的事件来轮询温度),我需要一个单独的命令来退出它。

我该如何编写这个脚本?

答案1

这可能会有用:

#!/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”结果,删除不需要的任何其他字符,以便 bash 可以将其视为数字,然后将其与您设置的任何目标温度进行比较。
我之所以要添加“NR+1000”,是grep 1001因为您可能会得到两个“temp1”结果sensors,就像我一样。这有点儿不方便,但确实有效。

然后,当你想杀死它时,只需killall script.sh

此行是为了避免繁忙等待导致的过度 CPU 消耗。如果您只想偶尔轮询温度,sleep 1可以将其更改为任意值。sleep duration

答案2

该脚本将影响以其中运行的进程为根的整个进程树。

您可以通过在终端中运行它并在另一个终端中使用检查温度来轻松测试它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分别将和设置$maxtemp5075;这些是阈值:1)低于该阈值,过程应该第一次启动,超过该阈值后继续;$maxtemp2)高于该阈值,过程应该停止;

  • trap 'pkill -g $pid; exit' 2确保脚本将终止进程组中的所有进程并在CTRL+时退出C

  • 第一个while循环无限期地空闲,直到温度数量超过$mintemp0当温度数量超过 时$mintemp0启动该过程,将其置于后台并跳出循环;

  • 第二个while循环无限期地空转,直到温度超过的数目$maxtemp大于;当温度超过0的数目时,向进程组发送 SIGSTOP 并启动第三个循环;第三个循环无限期地空转,直到温度超过的数目;当温度超过的数目时,向进程组发送 SIGCONT 并跳出循环。$maxtemp0whilewhile$mintemp0$mintemp0

答案3

剧本

#!/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

如何使用

  1. 将脚本复制到一个空文件中,另存为temp_run.py
  2. 运行它,最好进程运行(脚本将启动进程),随后是low_temp,,,high_tempprocess_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)"

相关内容