我有以下问题:动态生成的某些进程有吃100%CPU的倾向。我想将所有匹配某些标准(例如进程名称)的进程限制为一定的CPU百分比。
我想解决的具体问题是利用折叠@ home工作流程。我能想到的最好的解决方案是定期执行的perl脚本,并使用cpulimit实用程序来限制进程(如果您对更多细节感兴趣,请查看此blog post)。它有效,但它是一个黑客:/
有什么想法吗?我想将处理过程留给操作系统:)
再次感谢您的建议,但我们仍然忽略了这一点:)
“slowDown”解决方案基本上就是“cpulimit”实用程序的功能。我仍然需要关注哪些进程要减速,一旦工作进程完成就终止“slowDown”进程,并为新的进程进程启动新的进程。这正是我用Perl脚本和cron工作所做的。
主要问题是我事先不知道要限制哪些流程。它们是动态生成的。
也许有办法将一个用户的所有进程限制为一定的CPU百分比?我已经设置了一个用户来执行folding @ home作业,希望我能用/etc/security/limits.conf文件来限制他。但是最近的我可以得到的是每个用户的总CPU时间......
如果有一些能让你说出来的东西会很酷: “此用户进程的所有CPU%使用量的总和不能超过50%”。然后让流程争夺50%的CPU优先级......
伙计们,感谢您的建议,但这不是优先级 - 即使有足够的CPU时间,我也想限制CPU%。这些进程已经处于低优先级,因此它们不会导致任何性能问题。
我只想阻止CPU长时间以100%运行......
答案 0 :(得分:21)
我与gzip
有一个类似的问题。
假设我们想要减少gzip
进程的CPU:
gzip backup.tar & sleep 2 & cpulimit --limit 10 -e gzip -z
选项:
sleep
有用cpulimit
有时候没有立即获取新的gzip
流程--limit 10
将gzip
CPU使用率限制为10%-z
在cpulimit
流程完成时自动关闭gzip
另一个选择是运行cpulimit
守护程序。
答案 1 :(得分:13)
我不记得了,并且不认为unix调度程序中有这样的东西。您需要一个控制其他过程的小程序,并执行以下操作:
loop
wait for some time tR
send SIGSTOP to the process you want to be scheduled
wait for some time tP
send SIGCONT to the process.
loopEnd
比率tR / tP控制cpu负载。
这是一个小概念验证。 “忙”是一个耗尽你的cpu时间的程序,你希望通过“slowDown”减慢你的速度:
> cat > busy.c:
main() { while (1) {}; }
> cc -o busy busy.c
> busy &
> top
Tasks: 192 total, 3 running, 189 sleeping, 0 stopped, 0 zombie
Cpu(s): 76.9% us, 6.6% sy, 0.0% ni, 11.9% id, 4.5% wa, 0.0% hi, 0.0% si
Mem: 6139696k total, 6114488k used, 25208k free, 115760k buffers
Swap: 9765368k total, 1606096k used, 8159272k free, 2620712k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
26539 cg 25 0 2416 292 220 R 90.0 0.0 3:25.79 busy
...
> cat > slowDown
while true; do
kill -s SIGSTOP $1
sleep 0.1
kill -s SIGCONT $1
sleep 0.1
done
> chmod +x slowDown
> slowDown 26539 &
> top
Tasks: 200 total, 4 running, 192 sleeping, 4 stopped, 0 zombie
Cpu(s): 48.5% us, 19.4% sy, 0.0% ni, 20.2% id, 9.8% wa, 0.2% hi, 2.0% si
Mem: 6139696k total, 6115376k used, 24320k free, 96676k buffers
Swap: 9765368k total, 1606096k used, 8159272k free, 2639796k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
26539 cg 16 0 2416 292 220 T 49.7 0.0 6:00.98 busy
...
问候
答案 2 :(得分:7)
我认为在Linux中没有解决方案来限制CPU使用率,但是有一种可接受的方法可以将任何进程限制为某个CPU使用率:http://ubuntuforums.org/showthread.php?t=992706
如果他们删除了信息,请再次
安装包
安装cpulimit包。 代码:
sudo apt-get install cpulimit
安装gawk包。 代码:
sudo apt-get install gawk
创建CPULIMIT DAEMON文件
使用root权限打开文本编辑器并将bellow守护程序脚本文本保存到新文件/usr/bin/cpulimit_daemon.sh
代码:
#!/bin/bash
# ==============================================================
# CPU limit daemon - set PID's max. percentage CPU consumptions
# ==============================================================
# Variables
CPU_LIMIT=20 # Maximum percentage CPU consumption by each PID
DAEMON_INTERVAL=3 # Daemon check interval in seconds
BLACK_PROCESSES_LIST= # Limit only processes defined in this variable. If variable is empty (default) all violating processes are limited.
WHITE_PROCESSES_LIST= # Limit all processes except processes defined in this variable. If variable is empty (default) all violating processes are limited.
# Check if one of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST is defined.
if [[ -n "$BLACK_PROCESSES_LIST" && -n "$WHITE_PROCESSES_LIST" ]] ; then # If both variables are defined then error is produced.
echo "At least one or both of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST must be empty."
exit 1
elif [[ -n "$BLACK_PROCESSES_LIST" ]] ; then # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
NEW_PIDS_COMMAND="top -b -n1 -c | grep -E '$BLACK_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
elif [[ -n "$WHITE_PROCESSES_LIST" ]] ; then # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6' | grep -E -v '$WHITE_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
else
NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6 && \$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
fi
# Search and limit violating PIDs
while sleep $DAEMON_INTERVAL
do
NEW_PIDS=$(eval "$NEW_PIDS_COMMAND") # Violating PIDs
LIMITED_PIDS=$(ps -eo args | gawk '$1=="cpulimit" {print $3}') # Already limited PIDs
QUEUE_PIDS=$(comm -23 <(echo "$NEW_PIDS" | sort -u) <(echo "$LIMITED_PIDS" | sort -u) | grep -v '^$') # PIDs in queue
for i in $QUEUE_PIDS
do
cpulimit -p $i -l $CPU_LIMIT -z & # Limit new violating processes
done
done
CPU_LIMIT 如果要将每个进程的CPU消耗省略到任何其他百分比(20%),请在上面的脚本中更改此变量。请阅读&#34;如果使用SMP计算机&#34;如果您有SMP计算机(超过1个CPU或CPU超过1个核心),请参阅下文。
DAEMON_INTERVAL 如果您想要更多/更少的定期检查,请在上面的脚本中更改此变量。间隔以秒为单位,默认设置为3秒。
BLACK_PROCESS_LIST和WHITE_PROCESSES_LIST 变量BLACK_PROCESSES_LIST仅限制指定的进程。如果变量为空(默认),则所有违规过程都是有限的。
变量WHITE_PROCESSES_LIST限制除此变量中定义的进程之外的所有进程。如果变量为空(默认),则所有违规过程都是有限的。
BLACK_PROCESSES_LIST和WHITE_PROCESSES_LIST中的一个或两个变量必须为空 - 定义两个变量是不合逻辑的。
您可以使用分隔字符&#34; |&#34;在这两个变量之一中指定多个进程。 (没有双引号)。示例:如果你想cpulimit除了mysql,firefox和gedit进程之外的所有进程设置变量:WHITE_PROCESSES_LIST =&#34; mysql | firefox | gedit&#34;
在开机时间自动启动DAEMON的程序
为root用户设置文件权限: 代码:
sudo chmod 755 /usr/bin/cpulimit_daemon.sh
使用root权限打开文本编辑器并将下面的脚本保存到新文件/etc/init.d/cpulimit
代码:
#!/bin/sh
#
# Script to start CPU limit daemon
#
set -e
case "$1" in
start)
if [ $(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print $1}' | wc -l) -eq 0 ]; then
nohup /usr/bin/cpulimit_daemon.sh >/dev/null 2>&1 &
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon started successfully"; else print " * cpulimit daemon can not be started" }'
else
echo " * cpulimit daemon can't be started, because it is already running"
fi
;;
stop)
CPULIMIT_DAEMON=$(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print $1}' | wc -l)
CPULIMIT_INSTANCE=$(ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | wc -l)
CPULIMIT_ALL=$((CPULIMIT_DAEMON + CPULIMIT_INSTANCE))
if [ $CPULIMIT_ALL -gt 0 ]; then
if [ $CPULIMIT_DAEMON -gt 0 ]; then
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print $1}' | xargs kill -9 # kill cpulimit daemon
fi
if [ $CPULIMIT_INSTANCE -gt 0 ]; then
ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | xargs kill -9 # release cpulimited process to normal priority
fi
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon can not be stopped"; else print " * cpulimit daemon stopped successfully" }'
else
echo " * cpulimit daemon can't be stopped, because it is not running"
fi
;;
restart)
$0 stop
sleep 3
$0 start
;;
status)
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon is running"; else print " * cpulimit daemon is not running" }'
;;
esac
exit 0
代码:
sudo chown root:root /etc/init.d/cpulimit
代码:
sudo chmod 755 /etc/init.d/cpulimit
将脚本添加到启动过程目录: 代码:
sudo update-rc.d cpulimit defaults
重新启动以检查脚本是否在启动时启动cpulimit守护程序: 代码:
sudo reboot
手动检查,停止,启动和重启DAEMON
注意:本教程中的守护进程和服务具有相同的含义。
注意:对于使用Ubuntu 8.10之前的用户(如Ubuntu 8.04 LTS)而不是服务命令使用&#34; sudo /etc/init.d/cpulimit status / start / stop / restart&#34;语法或使用命令安装sysvconfig包:sudo apt-get install sysvconfig
检查cpulimit服务是否正在运行 检查命令返回:&#34; cpulimit守护程序正在运行&#34;如果服务正在运行,或者&#34; cpulimit守护程序未运行&#34;如果服务没有运行。 代码:
sudo service cpulimit status
启动cpulimit服务 您可以手动启动cpulimit守护程序,它将开始省略CPU消耗。 代码:
sudo service cpulimit start
停止cpulimit服务 停止命令会停止cpulimit守护程序(因此不会限制新进程),并且还会设置所有现有的有限进程以完全访问CPU,就像在cpulimit未运行之前一样。 代码:
sudo service cpulimit stop
重新启动cpulimit服务 如果更改/usr/bin/cpulimit_daemon.sh中的某些变量设置,如CPU_LIMIT,DAEMON_INTERVAL,BLACK_PROCESSES_LIST或WHITE_PROCESSES_LIST,则更改设置后必须重新启动服务。 代码:
sudo service cpulimit restart
没有守护进程 1.停止cpulimit守护进程(sudo service cpulimit stop) 2.在后台执行CPU密集型任务 3.执行命令:top并检查%CPU列 每个进程的%CPU结果可能超过20%。
启用守护程序 1.启动cpulimit守护进程(sudo service cpulimit start) 2.在后台执行相同的CPU密集型任务 3.执行命令:top并检查%CPU列 %CPU的结果应该是每个进程最多20%。 注意:开始时不要忘记%CPU可能超过20%,因为守护进程必须在3秒的间隔内捕获违规进程(默认情况下在脚本中设置)
我在英特尔双核CPU计算机上测试了这个代码 - 其行为类似于SMP计算机。不要忘记top命令和cpulimit默认情况下在Irix模式下运行,其中20%表示一个CPU的20%。如果有两个CPU(或双核),那么总CPU%可以是200%。在top命令中,可以使用命令I关闭Irix模式(在运行top命令时按+ i)并打开Solaris模式,其中CPU的总量除以CPU的数量,因此%CPU可以不超过100在任何数量的CPU计算机上%。请在顶部手册页中阅读有关top命令的更多信息(搜索I命令)。另请阅读cpulimit官方页面中有关cpulimit如何在SMP计算机上运行的更多信息。
但是cpulimit守护程序如何在SMP计算机上运行?始终处于Irix模式。因此,如果你想在2-CPU计算机上花费20%的CPU电量,那么40%应该用于cpulimit守护程序脚本中的CPU_LIMIT变量。
如果您想摆脱cpulimit守护程序,可以通过删除cpulimit守护程序并卸载cpulimit程序来清理系统。
停止cpulimit守护程序 代码:
sudo service cpulimit stop#停止cpulimit守护进程和所有cpulimit进程
从启动过程中删除守护程序 代码:
sudo update-rc.d -f cpulimit remove#删除符号链接
删除启动程序 代码:
sudo rm /etc/init.d/cpulimit#删除cpulimit启动脚本
删除cpulimit守护程序 代码:
sudo rm /usr/bin/cpulimit_daemon.sh#删除cpulimit守护程序脚本
卸载cpulimit程序 代码:
sudo apt-get remove cpulimit
卸载gawk程序 如果您不需要此程序用于任何其他脚本,则可以远程执行该程序。 代码:
sudo apt-get remove gawk
关于作者的说明
我刚刚为cpulimit编写了守护进程(上面的bash脚本)。我不是cpulimit项目的作者。如果您需要有关cpulimit计划的更多信息,请阅读官方cpulimit网页:http://cpulimit.sourceforge.net/。
此致 Abcuser
答案 3 :(得分:6)
为什么只能使用renice调整进程的优先级来限制CPU的百分比?使用renice并设置低优先级允许进程仍然使用100%的处理器(如果可用),但任何其他具有更高优先级的进程将在需要时获得该进程,几乎没有明显的延迟。
答案 4 :(得分:4)
我遇到了类似的问题,并且线程中提供的其他解决方案根本没有解决它。我的解决方案现在适用于我,但它不是最理想的,特别是对于流程由root拥有的情况 我现在的解决方法是非常努力地确保我没有root拥有的任何长时间运行的进程(比如只能以用户身份进行备份)
我刚为gnome安装了硬件传感器applet,并在CPU上设置了高温和低温警报,然后为每个警报设置以下命令:
低:
mv /tmp/hogs.txt /tmp/hogs.txt.$$ && cat /tmp/hogs.txt.$$ | xargs -n1 kill -CONT
高:
touch /tmp/hogs.txt && ps -eo pcpu,pid | sort -n -r | head -1 | gawk '{ print $2 }' >> /tmp/hogs.txt && xargs -n1 kill -STOP < /tmp/hogs.txt
好消息是我的电脑不再过热和崩溃。缺点是终端进程在停止时会从终端断开连接,并且在收到CONT信号时不会重新连接。另一件事是,如果它是导致过热的交互式程序(如某个Web浏览器插件!)那么它会在等待CPU冷却时在我正在做的事情中间冻结。在全球范围内进行CPU缩放处理会更好,但问题是我的CPU上只有两个可选设置,慢速设置不足以防止过热。
只是为了在这里重新进行迭代,这与进程优先级,重新组合没有任何关系,显然与停止运行很长时间的作业无关。这与防止CPU利用率长时间保持在100%有关,因为当满负荷运行时,硬件无法足够快地散热(空闲CPU产生的热量比满载CPU少)。
其他一些可能有用的明显可能性是:
降低BIOS中的整体CPU速度
更换散热片或重新涂抹热凝胶,看看是否有帮助
用一些压缩空气清洁散热器
更换CPU风扇
[编辑] 注意:当我禁用BIOS中的可变风扇速度时,100%CPU不会再出现过热(asus p5q pro turbo)。 CPU满载时,每个核心最高可达49摄氏度。
答案 5 :(得分:2)
我还需要限制某些进程的CPU时间。 Cpulimit是一个很好的工具,但我总是不得不手动找出PID并手动启动cpulimit,所以我想要更方便的东西。
我想出了这个bash脚本:
#!/bin/bash
function lp
{
ps aux | grep $1 | termsql "select COL1 from tbl" > /tmp/tmpfile
while read line
do
TEST=`ps aux | grep "cpulimit -p $line" | wc -l`
[[ $TEST -eq "2" ]] && continue #cpulimit is already running on this process
cpulimit -p $line -l $2
done < /tmp/tmpfile
}
while true
do
lp gnome-terminal 5
lp system-journal 5
sleep 10
done
此示例将每个gnome-terminal实例的cpu时间限制为5%,将每个system-journal实例的cpu时间限制为5%。
我在本例中使用了另一个名为termsql的脚本来提取PID。你可以在这里得到它: https://gitorious.org/termsql/termsql/source/master:
答案 6 :(得分:2)
使用cgroups&#39; cpu.shares 不执行任何 nice 值不会做的事情。听起来你想要真正限制流程,这绝对可以完成。
您需要使用一两个脚本,和/或编辑 /etc/cgconfig.conf 来定义所需的参数。
具体来说,您要编辑值 cpu.cfs_period_us 和 cpu.cfs_quota_us 。然后,每个 cpu.cfs_period_us 微秒,将允许该进程运行 cpu.cfs_quota_us 微秒。
例如:
如果 cpu.cfs_period_us = 50000 和 cpu.cfs_quota_us = 10000 ,则无论发生什么其他情况,该进程都将获得最多20%的CPU时间。
在这个截图中,我给了进程2%的CPU时间:
就流程而言,它的运行率为100%。
设置 cpu.shares 另一方面可以并且仍将使用100%的空闲CPU时间。
在这个类似的例子中,我给出了 cpu.shares = 100 (1024)的过程:
正如您所看到的,该过程仍在消耗所有空闲的CPU时间。
参考文献:
http://manpages.ubuntu.com/manpages/precise/man5/cgconfig.conf.5.html http://kennystechtalk.blogspot.co.uk/2015/04/throttling-cpu-usage-with-linux-cgroups.html
答案 7 :(得分:2)
在使用systemd
的系统中,可以使用以下命令来以CPU使用率最大化运行单个进程:
sudo systemd-run --scope --uid=1000 -p CPUQuota=20% my_heavy_computation.sh
这将最多使用20%的单个CPU内核(如果使用超线程,则将使用CPU线程)。
答案 8 :(得分:1)
我至少看到两个选项:
答案 9 :(得分:1)
PS + GREP + NICE
答案 10 :(得分:1)
您可以使用cgroup限制cpu时间。操作系统将处理资源管理,就像您在问题中要求的那样。
这是一个包含示例的wiki:https://wiki.archlinux.org/index.php/Cgroups
由于流程已作为单独的用户运行,因此限制该用户的所有流程应该是最简单的解决方案。
答案 11 :(得分:0)
nice命令可能会有所帮助。
答案 12 :(得分:0)
这可以使用setrlimit(2)完成(特别是通过设置RLIMIT_CPU参数)。
答案 13 :(得分:0)
在那里投入一些睡眠呼叫应该强制进程离开CPU一段时间。如果您每分钟睡30秒,那么您的过程在该分钟内的平均CPU使用率不应超过50%。
答案 14 :(得分:-1)
您可以缩小CPU频率。那么您不必担心个别流程。当你需要更多的cpu时,请重新调整频率。
答案 15 :(得分:-1)
我真的不明白为什么要限制CPU时间......你应该限制该机器的总负载,负载主要由IO操作决定。 例如:如果我创建while(1){}循环,它将使总负载达到1.0,但如果此循环执行某些磁盘写入,则负载跳转到2.0 ... 4.0。这就是杀死你的机器,而不是CPU的使用。可以通过nice / renice轻松处理CPU使用率。
无论如何,当负载过高时,你可以制作一个为特定PID执行'kill -SIGSTOP PID'的脚本,并在一切恢复正常时杀死-SIGCONT ...... PID可以由使用'px aux'命令,因为我看到它显示CPU使用率,你应该能够使用该列对列表进行排序。我认为这一切都可以用bash来完成......