我想编写一个简短的脚本,手动启动一次,然后应该:
- 如果全部气温低于
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
分别将和设置$maxtemp
为50
和75
;这些是阈值:1)低于该阈值,过程应该第一次启动,超过该阈值后继续;$maxtemp
2)高于该阈值,过程应该停止;trap 'pkill -g $pid; exit' 2
确保脚本将终止进程组中的所有进程并在CTRL+时退出C;第一个
while
循环无限期地空闲,直到温度数量超过$mintemp
;0
当温度数量超过 时$mintemp
,0
启动该过程,将其置于后台并跳出循环;第二个
while
循环无限期地空转,直到温度超过的数目$maxtemp
大于;当温度超过0
的数目时,向进程组发送 SIGSTOP 并启动第三个循环;第三个循环无限期地空转,直到温度超过的数目;当温度超过的数目时,向进程组发送 SIGCONT 并跳出循环。$maxtemp
0
while
while
$mintemp
0
$mintemp
0
答案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
如何使用
- 将脚本复制到一个空文件中,另存为
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)"