拉升CPU脚本
本文最后更新于 2024-08-10,文章内容已经超过7天没更新了。
项目在开发过程中难免会遇到服务器cpu使用率过低的情况,有些甲方会以服务器cpu使用率过低为理由回收我们的服务器资源,为了保持服务器资源充足,以及保证在特殊情况下服务器请求压力过大而导致资源不足的情况,下边给大家分享一个拉升cpu使用率的shell脚本
1、脚本
先展示脚本
#!/bin/bash
declare -a pid_array
kill_all(){
for i in "${pid_array[@]}"; do
`kill -9 $i`
echo 'kill ' $i ';';
done
unset pid_array;
echo "kill_all; unset pid_array";
}
CPU_hope=5000;
TIME_limit=1;
if [ -n "$1" ]
then
expr $1top "+" 10 &> /dev/null
if [ $? -eq 0 ];then
CPU_hope=$(printf "%.0f" `echo "scale=2;$1*100" |bc`);
else
echo "$1 not number";
echo "USAGE: $0 <CPU_use%>";
exit 1;
fi
fi
if [ -n "$2" ]
then
expr $2 "+" 10 &> /dev/null
if [ $? -eq 0 ];then
TIME_limit=$2;
else
echo "$2 not number";
echo "USAGE: $0 <CPU_use%> <TIME_limit>";
exit 1;
fi
fi
CURRENT_HOUR=$(date +%H)
START_HOUR=0
END_HOUR=24
if [ -n "$3" ]
then
expr $3 "+" 10 &> /dev/null
if [ $? -eq 0 ];then
START_HOUR=$3
else
echo "$3 not number";
echo "USAGE: $0 <CPU_use%> <TIME_limit> <START_HOUR>";
exit 1;
fi
fi
if [ -n "$4" ]
then
expr $4 "+" 10 &> /dev/null
if [ $? -eq 0 ];then
END_HOUR=$4
else
echo "$4 not number";
echo "USAGE: $0 <CPU_use%> <TIME_limit> <START_HOUR> <END_HOUR>";
exit 1;
fi
fi
if [ $START_HOUR -lt 0 ] || [ $START_HOUR -gt 24 ] || [ $END_HOUR -lt 0 ] || [ $END_HOUR -gt 24 ]; then
echo "$3 and $4 range is 0-24"
exit 1
fi
if [ $START_HOUR -ge $END_HOUR ]; then
echo "$3 must be less than $4"
exit 1
fi
DATESTRINT=$(date +%Y%m%d%H%M --date="+$TIME_limit hour")
script_abs=$(readlink -f "$0")
script_dir=$(dirname $script_abs)
if [ -e $script_dir/run.signal ]
then
echo "Service is already running!";
exit 1;
fi
touch $script_dir/run.signal
rm -f $script_dir/quit.signal
echo "************begin MM***author:Cary Wen************"
echo "CPU_hope:$CPU_hope";
echo "DATESTRINT:$DATESTRINT";
CPU_count=`cat /proc/cpuinfo | grep 'processor' | wc -l`;
echo "CPU_count:$CPU_count";
CURRENT_TIME=$(printf "%.0f" $(date +%Y%m%d%H%M))
echo "========================CURRENT_TIME:$CURRENT_TIME========================"
while [ $CURRENT_TIME -lt $DATESTRINT ]
do
CPU_idle=`mpstat -P ALL 1 1 |grep "all" |sed -n '2p' |awk -F" " '{print $NF}'`;
CPU_use=$(printf "%.0f" `echo "scale=2;(100-$CPU_idle)*100" |bc`);
echo "CPU_use:$CPU_use;CPU_idle:$CPU_idle";
echo "CURRENT_HOUR:$CURRENT_HOUR;START_HOUR:$START_HOUR;END_HOUR:$END_HOUR";
if [ $CURRENT_HOUR -ge $START_HOUR ] && [ $CURRENT_HOUR -lt $END_HOUR ]; then
if [ $CPU_hope -eq $CPU_use ]
then
echo 'CPU_hope == CPU_use';
elif [ $CPU_hope -gt $CPU_use ]
then
PROC_count=`echo "scale=2;(($CPU_hope-$CPU_use)*$CPU_count+4999)/10000" |bc`;
echo "PROC_count:$PROC_count";
PROC_count=$(printf "%.0f" $PROC_count); #四舍五入的
echo "append PID count:$PROC_count";
PID_ARRAY_CUT=${#pid_array[@]};
PID_ARRAY_BEGIN=$PID_ARRAY_CUT;
PID_ARRAY_END=$(( $PID_ARRAY_CUT + $PROC_count - 1 ))
echo "PID_ARRAY_CUT:$PID_ARRAY_CUT;PID_ARRAY_BEGIN:$PID_ARRAY_BEGIN;PID_ARRAY_END:$PID_ARRAY_END";
for i in `seq $PID_ARRAY_BEGIN $PID_ARRAY_END`
do
echo -ne "
i=0;
while true
do
i=100+100;
done" | /bin/sh &
pid_array[$i]=$!;
echo 'start ' $! ';';
done
else
PROC_count=`echo "scale=0;(($CPU_use-$CPU_hope)*$CPU_count)/10000" |bc`
echo "delete PID count:$PROC_count";
if [ $PROC_count -gt 0 ] ;then
PID_ARRAY_CUT=${#pid_array[@]};
if [ $PID_ARRAY_CUT -eq 0 ];
then
echo "exists PID count:$PID_ARRAY_CUT";
elif [ $PID_ARRAY_CUT -gt $PROC_count ]
then
PID_ARRAY_BEGIN=$(( $PID_ARRAY_CUT - 1 ));
PID_ARRAY_END=$(( $PID_ARRAY_CUT - $PROC_count ))
echo "PID_ARRAY_CUT:$PID_ARRAY_CUT;PID_ARRAY_BEGIN:$PID_ARRAY_BEGIN;PID_ARRAY_END:$PID_ARRAY_END";
for i in `seq $PID_ARRAY_BEGIN -1 $PID_ARRAY_END`
do
PID_ID=${pid_array[$i]};
`kill -9 $PID_ID`
unset pid_array[$i];
echo "kill ${PID_ID}; unset pid_array[${i}]";
done
else
kill_all;
fi
fi
fi
else
kill_all;
fi
sleep 30s
if [ -e $script_dir/quit.signal ]
then
echo "break while!";
break;
fi
CURRENT_TIME=$(printf "%.0f" $(date +%Y%m%d%H%M))
CURRENT_HOUR=$(date +%H)
echo "========================CURRENT_TIME:$CURRENT_TIME========================";
done
echo "Shutting down ..........";
kill_all;
echo "***********************end***********************"
rm -f $script_dir/run.signal
exit 0;
2、脚本使用
接下来在服务器上新建一个目录,把上述脚本main.sh放到目录下,创建一个运行脚本 start.sh,运行脚本用来初始化运行参数,并后台运行内容如下
nohup sh main.sh [a] [b] [c] [d] > main-log.log 2>&1 & echo $! > main-log.pid
参数介绍
a: cpu使用率拉升至,默认50%。例如35,表示将cpu使用率拉升至35%
b: 拉升持续时间,默认1h,单位:h。例如10,表示脚本持续拉升时间是10个小时
c: 拉升开始时间,默认0,单位:h。例如10,表示每天的10点开始
d: 拉升结束时间,默认24,单位:h。例如21,表示每天的21点结束
注意:参数b可能会和c、d冲突,例如需要拉升的时间是1个小时,指定的执行时间是20-24,但是当前系统时间是10,那么脚本是不会执行的
上述运行脚本会在目录下创建两个文件,main-log.log是脚本运行日志文件,可以查看脚本运行打印的日志,main-log.pid是脚本运行的pid,如果想停止拉升cpu可以直接kill掉这个pid
当然,脚本也提供了另外一种更安全的停止方式,在脚本目录 touch quit.signal
创建一个quit.signal文件,脚本会kill掉所有正在拉升的进程
3、脚本介绍
脚本的核心是下边这部分代码
do
echo -ne "
i=0;
while true
do
i=100+100;
done" | /bin/sh &
pid_array[$i]=$!;
echo 'start ' $! ';';
done
这段代码会循环创建一个计算的进程,使cpu使用率达到预设的百分比
pid_array记录了所有循环创建的进程,kill_all()方法会kill掉所有的进程
if [ -e $script_dir/quit.signal ]
then
echo "break while!";
break;
fi
这段代码会判断工作目录下有没有quit.signal文件,如果有则跳出循环,然后kill掉所有进程
当然,脚本里也做了安全控制,如果cpu使用率超过了预定的百分比,脚本会自动根据当前使用率选择性地kill掉某些进程,直到所有进程都kill掉,完全不会影响其他程序需要cpu的时候