近期遇到一个比较奇怪的需求:某台服务器的内存长期处于闲置状态,服务商可能会通知回收资源或调整配置。

既然有这样的情况,就记录一下我与 AI 沟通后尝试的一种方法:使用 Python 分配一块内存,并通过 systemd 管理程序的后台运行。

本文属于个人实验记录,不代表该方法一定能够避免服务商回收资源或调整配置。 实际操作前,请先确认服务商的资源使用政策,并评估对服务器上其他业务的影响。

一、准备工作

首先确认服务器已经安装 Python 3。

python3 --version

如果尚未安装,请根据当前 Linux 发行版安装相应的软件包。

开始之前,还需要确认服务器当前的可用内存,以及其他业务的实际内存需求。不要直接按照服务器的总内存设置分配量,以免触发 OOM Killer,导致其他业务受到影响。

二、创建 Python 程序

创建一个 Python 文件,例如 memhold.py。

vim /opt/memhold.py

写入以下内容:

#!/usr/bin/env python3

import time

# 计划分配的内存大小,单位为 GB
# 请根据实际可用内存谨慎调整
SIZE_GB = 1

# 分配内存
buf = bytearray(SIZE_GB * 1024 * 1024 * 1024)

# 每隔 4096 字节写入一次,触碰分配的内存页
# 使对应页面实际获得物理内存支持
for i in range(0, len(buf), 4096):
    buf[i] = 1

print("memory allocated", flush=True)

# 保持程序运行,避免内存被程序主动释放
while True:
    time.sleep(600)

保存后,可以先在终端中进行测试。

python3 /opt/memhold.py

程序正常启动后,会输出:

memory allocated

测试完成后,使用 Ctrl+C 结束前台进程。

注意: 示例默认分配 1 GiB 内存,并不意味着所有服务器都适合这个数值。bytearray 分配和逐页写入可能明显增加实际内存占用;分配失败、系统内存不足或进程被终止时,程序也可能无法按预期运行。

三、配置 systemd 后台服务

如果需要由 systemd 管理程序,可以创建服务配置文件:

vim /etc/systemd/system/memhold.service

写入以下内容:

[Unit]
Description=Memory Holder
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/nice -n 19 /usr/bin/python3 /opt/memhold.py
Restart=no
OOMScoreAdjust=900

[Install]
WantedBy=multi-user.target

配置说明

配置项说明
Description服务描述
Type=simple直接运行指定程序
ExecStart指定 Python 程序的启动命令
Restart=no程序退出后不自动重启,避免反复重新分配内存
OOMScoreAdjust=900提高进程被 OOM Killer 选中的倾向,但不保证一定优先被终止
WantedBy=multi-user.target用于配置常规多用户运行级别下的开机启动

其中,nice -n 19 用于降低进程的 CPU 调度优先级,并不代表它会自动降低内存使用量。

OOMScoreAdjust=900 是一个偏高的值,目的是让该进程在内存不足时更容易成为 OOM Killer 的选择对象。但实际选择结果仍取决于系统状态和其他进程的情况,不能把它理解为绝对的保护机制。

这里使用 Restart=no,是为了避免程序被系统终止后,systemd 又立即启动程序并重新申请大量内存。如果需要调整重启策略,应先评估反复分配内存可能带来的影响。

四、加载配置并启动服务

保存配置后,执行以下命令:

systemctl daemon-reload
systemctl enable --now memhold

这两条命令分别用于重新加载 systemd 服务定义,以及设置开机启动并立即启动服务。

查看服务状态

systemctl status memhold

如果需要查看最近的运行日志:

journalctl -u memhold -n 100 --no-pager

如果服务启动失败,应优先检查 Python 路径、脚本路径、可用内存以及系统日志。

五、查看内存占用与运行情况

5.1 查看系统整体内存

free -h

也可以使用:

top

通过这些工具观察系统整体内存使用情况,以及是否出现明显的内存压力。

5.2 查看目标进程

pgrep -af memhold.py

如果需要进一步观察进程资源使用情况,可以使用:

ps -C python3 -o pid,ni,rss,vsz,cmd

其中:

  • PID:进程 ID。
  • NI:进程的 nice 值。
  • RSS:进程当前驻留在物理内存中的内存量,单位为 KiB。
  • VSZ:进程的虚拟内存大小,单位为 KiB。

需要注意,虚拟内存大小、实际驻留内存和系统整体内存使用量是不同的指标,不能简单地将它们视为同一个数值。

5.3 观察系统是否出现异常

测试过程中,建议重点关注:

  • 其他业务是否出现响应变慢或异常退出。
  • 系统是否发生 OOM 事件。
  • 目标进程是否意外退出。
  • 系统日志中是否出现内存不足相关信息。

可以使用以下命令检查内核日志:

journalctl -k --since "1 hour ago" --no-pager

如果出现内存不足、业务异常或明显的系统压力,应及时停止实验。

六、如何停止服务

如果需要停止程序,并取消开机启动,可以执行:

systemctl disable --now memhold

其中,--now 会立即停止当前服务,disable 则会取消其开机启动设置。

随后可以确认服务状态:

systemctl status memhold

如果需要彻底删除该服务,还应在停止服务后删除 /etc/systemd/system/memhold.service,再执行:

systemctl daemon-reload

删除服务定义不会自动删除 Python 脚本,/opt/memhold.py 是否保留,可以根据实际需要决定。

七、最后的一些说明

这次实验主要涉及 Python 内存分配、Linux 进程资源使用,以及 systemd 后台服务管理。

有几点需要特别注意:

  1. 内存占用不等于有效业务负载。 主动申请内存并不能证明服务器产生了实际业务价值。
  2. 不要忽视其他业务的资源需求。 内存压力可能导致关键进程被终止,影响整台服务器的稳定性。
  3. 不要把 OOM 优先级设置当作绝对保障。 OOMScoreAdjust 只会影响 OOM Killer 的选择倾向。
  4. 服务商的资源政策仍然有效。 如果服务商对资源使用有明确要求,应优先遵守相关条款,而不是依靠人为制造内存占用来规避资源回收或配置调整。

完结,撒花。