Linux中基于Python2.7.5实现的CPU压力工具
脚本作用
由于某些特殊原因,需要保持服务器的CPU使用率在一个水平线以上,因此制作了这个脚本,目标是在不依赖其他组件的情况下使用Python脚本增加服务器的CPU压力。
使用要求
- Linux
- Python 2.7.5
创建脚本
首先使用创建脚本文件
/usr/local/cpu-loader/cpu_loader.py
授予脚本运行权限
chmod +x /usr/local/cpu-loader/cpu_loader.py
编辑脚本文件内容 vim /usr/local/cpu-loader/cpu_loader.py
#!/usr/bin/env python # -*- coding: utf-8 -*- """ CPU 负载维持服务 - Python 2.7.5 """ from __future__ import print_function import os import sys import time import signal import math import random import logging.handlers import errno PID_FILE = "/tmp/cpu_loader.pid" LOG_FILE = "/tmp/cpu_loader.log" TARGET = 6.0 # 目标CPU% TOLERANCE = 1.0 # 容差 MAX_LOG_BYTES = 2 * 1024 * 1024 MAX_LOG_BACKUPS = 3 class Monitor(object): def __init__(self): self.prev = None def get(self): try: with open('/proc/stat') as f: fields = map(int, f.readline().split()[1:]) fields = list(fields) idle = fields[3] + fields[4] total = sum(fields) if self.prev is None: self.prev = (idle, total) return 0.0 pidle, ptotal = self.prev self.prev = (idle, total) diff_idle = idle - pidle diff_total = total - ptotal if diff_total == 0: return 0.0 return 100.0 * (1.0 - float(diff_idle) / diff_total) except: return 0.0 class CPULoader(object): def __init__(self): self.running = False self.monitor = Monitor() self.logger = None self.work_ratio = 0.0 # 工作时长占比 (0.0-1.0) self.idle_mode = False def setup_logging(self, foreground=False): self.logger = logging.getLogger('CPULoader') self.logger.setLevel(logging.INFO) self.logger.handlers = [] handler = logging.handlers.RotatingFileHandler( LOG_FILE, maxBytes=MAX_LOG_BYTES, backupCount=MAX_LOG_BACKUPS ) handler.setFormatter(logging.Formatter( '%(asctime)s [%(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S' )) self.logger.addHandler(handler) if foreground: console = logging.StreamHandler(sys.stdout) self.logger.addHandler(console) def log(self, msg, level=logging.INFO): if self.logger: self.logger.log(level, msg) def read_pid(self): try: if os.path.exists(PID_FILE): with open(PID_FILE, 'r') as f: return int(f.read().strip()) except: return None def write_pid(self, pid): with open(PID_FILE, 'w') as f: f.write(str(pid)) def remove_pid(self): if os.path.exists(PID_FILE): os.remove(PID_FILE) def do_work(self, duration_sec): """高强度计算,优化以最大化CPU占用""" if duration_sec <= 0: return start = time.time() # 使用更密集的整数运算(比浮点math函数更消耗CPU) x = random.randint(10000, 99999) iterations = 0 while time.time() - start < duration_sec: # 内层循环减少time.time()调用开销 for _ in range(5000): # 高强度整数运算,确保CPU无法预测优化 x = (x * 123456789 + 987654321) & 0xFFFFFFFF x = ((x << 13) | (x >> 19)) & 0xFFFFFFFF # 位旋转 x = (x * x + 12345) & 0xFFFFFFFF iterations += 1 def run_service(self): self.running = True self.log("服务启动 | 目标CPU: {}% | 单线程增强版".format(TARGET)) # 初始化CPU监控 self.monitor.get() time.sleep(1) cycle_count = 0 last_check_time = time.time() try: while self.running: # 动态调整检测周期:负载低时延长,负载高时缩短 current_time = time.time() elapsed = current_time - last_check_time last_check_time = current_time cpu = self.monitor.get() error = cpu - TARGET # 正误差=过高,负=过低 # 快速上升,缓慢下降策略 if error < -TOLERANCE: # CPU过低(低于5%) # 误差越大,增加越快(加速逼近目标) increment = max(0.02, min(0.1, abs(error) * 0.02)) self.work_ratio += increment elif error > TOLERANCE: # CPU过高(高于7%) # 缓慢减少,避免震荡 self.work_ratio -= 0.015 else: # 在容差内(5%-7%),微调 if error > 0: self.work_ratio -= 0.005 else: self.work_ratio += 0.005 # 关键修复:放宽上限到100%,允许满负载运转 self.work_ratio = max(0.0, min(1.0, self.work_ratio)) # 判断是否空闲模式(work_ratio接近0且CPU远低于目标) self.idle_mode = (self.work_ratio < 0.001 and cpu < TARGET * 0.3) # 自适应周期:根据误差动态调整 if abs(error) > 3.0: cycle_time = 0.2 # 偏差大时,200ms周期快速调整 else: cycle_time = 1.0 # 接近目标时,1秒周期稳定运行 work_time = self.work_ratio * cycle_time sleep_time = cycle_time - work_time # 工作阶段 if work_time > 0.001: self.do_work(work_time) # 休眠阶段 if self.idle_mode: # 空闲模式:大幅延长检测周期 time.sleep(5.0) self.log("CPU: {:5.1f}% | 空闲模式 | 工作比: {:.1f}%".format( cpu, self.work_ratio * 100)) else: # 确保最少休眠1ms,避免CPU空转 time.sleep(max(0.001, sleep_time)) cycle_count += 1 # 每5秒记录一次日志(减少IO) if cycle_count % 5 == 0: self.log("CPU: {:5.1f}% | 目标: {}% | 工作比: {:.1f}% | 误差: {:+.1f}%".format( cpu, TARGET, self.work_ratio * 100, error)) except Exception as e: self.log("错误: {}".format(str(e)), logging.ERROR) finally: self.log("服务停止") def daemonize(self): try: pid = os.fork() if pid > 0: sys.exit(0) except OSError: sys.exit(1) os.chdir("/") os.setsid() os.umask(0) try: pid = os.fork() if pid > 0: sys.exit(0) except OSError: sys.exit(1) sys.stdout.flush() sys.stderr.flush() with open(os.devnull, 'r') as f: os.dup2(f.fileno(), sys.stdin.fileno()) with open(os.devnull, 'a+') as f: os.dup2(f.fileno(), sys.stdout.fileno()) os.dup2(f.fileno(), sys.stderr.fileno()) def start(self): pid = self.read_pid() if pid: try: os.kill(pid, 0) print("服务已在运行 (PID: {})".format(pid)) return except: pass print("正在启动...") self.setup_logging(foreground=False) self.daemonize() self.setup_logging(foreground=False) self.write_pid(os.getpid()) try: self.run_service() finally: self.remove_pid() def stop(self): pid = self.read_pid() if not pid: print("服务未运行") return try: os.kill(pid, signal.SIGTERM) time.sleep(0.5) for _ in range(10): try: os.kill(pid, 0) time.sleep(0.3) except OSError: break print("服务已停止") except OSError: print("进程已不存在") finally: self.remove_pid() def status(self): pid = self.read_pid() if pid: try: os.kill(pid, 0) print("● 运行中 | PID: {} ".format(pid)) return except: pass print("○ 未运行") def run_foreground(self): self.setup_logging(foreground=True) print("前台运行 | 目标CPU: {}% | Ctrl+C停止\n".format(TARGET)) try: self.run_service() except KeyboardInterrupt: self.running = False print("\n已停止") def main(): if len(sys.argv) < 2: print("用法: {} {{start|stop|status|run}}".format(sys.argv[0])) return loader = CPULoader() if sys.argv[1] == "start": loader.start() elif sys.argv[1] == "stop": loader.stop() elif sys.argv[1] == "status": loader.status() elif sys.argv[1] == "run": loader.run_foreground() else: print("未知命令") if __name__ == "__main__": main()
保存文件后尝试执行
/usr/local/cpu-loader/cpu_loader.py run #前台运行 /usr/local/cpu-loader/cpu_loader.py start #后台运行 /usr/local/cpu-loader/cpu_loader.py stop #停止运行 /usr/local/cpu-loader/cpu_loader.py status #运行状态
注册成系统服务
创建服务文件
touch /etc/systemd/system/cpu-loader.service
在文件中输入以下内容
[Unit] Description=CPU Loader Service After=network.target [Service] Type=forking PIDFile=/usr/local/cpu-loader/cpu_loader.pid ExecStart=/usr/bin/python /usr/local/cpu-loader/cpu_loader.py start ExecStop=/usr/bin/python /usr/local/cpu-loader/cpu_loader.py stop Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
启动服务并设置开机启动
# 重新加载 systemd sudo systemctl daemon-reload # 设置开机自启 sudo systemctl enable cpu-loader # 立即启动 sudo systemctl start cpu-loader # 查看状态 sudo systemctl status cpu-loader

浙公网安备 33010602011771号