TW●汤伟的数字生活NOTES ON A DIGITAL LIFE
个人数字生活文库始于 2026 · 持续修订总目录 ↗
全部文章

Linux 运维 / 实战手册

Linux 进程、内存与日志:先建立证据链,再考虑重启

区分进程状态、可用内存、容器限制与 systemd 服务日志,避免用清缓存和强杀代替定位。

阅读设置字号仅保存在当前浏览器

先确认你看到的是哪一层进程

页面请求卡住时,“服务还在”只能排除部分原因。先区分浏览器、反向代理、应用进程和它依赖的存储,再确定自己的诊断终端在宿主机还是容器中。同一进程在不同 PID 命名空间中可能有不同编号;从旧截图抄来的 PID 也可能已经被别的进程复用。本文的 12345 只是占位值,必须由本人服务界面或可信运行记录确认后替换。

/proc 提供内核当前状态的窗口,读取状态文件比批量转储所有命令行或环境变量更容易控制范围。环境变量和启动参数可能携带密钥,本手册不建议导出它们。权限拒绝通常需要先理解进程隔离与访问策略,不应立刻提升权限读取别人的进程。read 命令可能暴露路径与身份,也会消耗资源;本篇没有连接任何设备执行诊断。

查看指定进程的内存与状态bash · Linux(/proc、cat)
查询 / 诊断
cat /proc/12345/status

12345 是示例 PID,必须换成已确认属于自己服务的 PID;State、VmRSS、VmSwap、Threads 分别帮助查看状态、常驻内存、交换和线程。 示意:State: S (sleeping)、VmRSS: 32768 kB;睡眠不代表故障。 不存在可能进程已退出;权限拒绝可能来自 hidepid 或命名空间。PID 会重用,不能用旧记录决定终止进程。

先给一次失败建立时间线与最小记录

本篇要完成的任务是为一个由系统服务管理器运行的个人应用定位“启动后页面不可用”的原因,并在修正后用同一请求验收。假设已有名为 personal-app.service 的个人服务,且你掌握其配置和维护方式;这只是占位名称,本文不会创建或连接真实服务。开始前记录实际服务名、当前时间与时区、请求入口、最后一次已知正常时间,以及最近是否修改了配置。没有真实服务的读者可以阅读示意推理,不必为了运行命令去安装后台程序。

把现象拆成三种:服务根本没有进入运行状态,服务进入运行后退出,服务持续运行但请求失败。第一种优先看启动结果和配置解析,第二种看退出信息与相邻日志,第三种把端口和应用请求加入证据链。这样能避免一看到网页卡住就去查内存,也能避免把后台进程存在当成业务正常。记录只保留当前诊断需要的字段,启动参数和环境变量可能含私密内容,没必要为了填满报告全部导出。

查询服务的主进程编号后,再读取对应进程状态,二者应尽量在相近时间取得。主进程为零时表示没有可用于这一检查的运行主进程,不应继续把零或旧编号拼入路径。服务可能快速重启,刚取得的编号随后就消失;此时返回服务状态和日志观察重启过程,不把文件不存在判断成内核异常。若管理的是用户服务,要一致使用用户管理器的查询入口,不能将系统服务和用户服务的同名结果混用。

查询与启动失败相关的有限属性bash · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
查询 / 诊断
systemctl show personal-app.service --property=LoadState,ActiveState,SubState,MainPID,Result,ExecMainCode,ExecMainStatus,NRestarts

read:示例假定系统级服务;属性是否提供与 systemd 版本有关。

记录当前时间bash · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
查询 / 诊断
date --iso-8601=seconds

read:GNU date;Mac/BSD 可用 date -u 记录 UTC,但不照抄此 GNU 长选项。

systemd 命令有明确适用边界

systemctl 面向运行 systemd 管理器的系统。精简容器通常没有完整的系统服务管理环境,看到总线连接失败不代表需要在容器里安装 systemd。DSM 也不能被当作普通 GNU/Linux 发行版管理:厂商服务应优先使用 DSM 受支持界面,BusyBox 工具选项与 GNU 不同。本篇服务命令只针对明确由 systemd 管理的个人 Linux 主机。

status 适合人读,服务 active 仅代表管理器认为它处于活动状态,不保证 HTTP 健康检查成功。反过来,一次性任务正常结束也可能是 inactive。先识别服务类型、主进程和最后退出信息,再查对应时间日志。服务名不存在时先核对实际单元,尤其是用户服务与系统服务的区别;不要尝试重启名称相近但用途未知的服务。

读取 systemd 服务状态bash · Linux(运行 systemd 的主机)
查询 / 诊断
systemctl --no-pager status personal-app.service

status 显示服务当前状态、主进程及最近日志,--no-pager 避免交互分页;服务名是待替换的个人示例。 示意:active (running) 或 failed;非零退出也可能只表示服务未运行。 Unit not found 先核对真实单元名;总线连接失败先确认是否在容器中,不能直接安装或启动 systemd。

把日志范围收敛到一次故障

一份有用的故障记录应包含发生时间与时区、请求表现、服务状态和相邻日志。先看半小时内某个单元的末尾两百条,不要直接导出整个 journal。日志量大时,仅看末尾可能错过最初触发点,应围绕已确定的时间窗口前后扩展。错误重复出现时,记录第一次、最后一次与频率,比粘贴几千条同样的堆栈更利于判断。

空日志并不等于应用正常:应用可能只写文件、输出到容器日志系统,或 journal 权限与保留策略使记录不可见。磁盘满也可能影响日志保存。需要回到应用支持的日志位置确认去向,不能为了有输出而修改服务。分享前把请求令牌、个人用户名、私有域名和完整文件路径删除,只保留必要字段与错误顺序。

按服务和时间收集日志bash · Linux(systemd-journald)
查询 / 诊断
journalctl --no-pager -u personal-app.service --since '30 minutes ago' -n 200

-u 过滤单元,--since 限定时间,-n 限制最多末尾 200 条;日志可能包含路径、请求信息,分享前脱敏。 示意:显示这段时间内该单元的日志;没有条目不等于没有错误。 权限不足、时区误差、日志未进 journal 或已轮转都可能导致空结果;先确认日志去向,不立即提权导出全机日志。

示意案例:配置读取失败,而不是内存耗尽

下面用一组明确标为示意的日志关系说明推理:应用启动后报告无法读取个人配置,接着主进程以失败状态退出,管理器按策略尝试再次启动。它没有声称来自真实运行,也没有借用某个应用固定的退出码。遇到类似序列,首先保存首次应用错误和随后的管理器结果;最后一条“启动失败”只描述结果,最前面的文件读取错误才更接近触发原因。

接下来核对服务实际运行身份、配置路径和逐级父目录权限,沿用文件权限篇的方法。若最近移动了配置目录,新的父目录可能不允许该身份穿越;若配置路径是相对路径,服务工作目录与交互终端不同也可能导致找错文件。只有证据表明是哪一项不符合预期,才修改那一项。此时内存可用量看起来正常只能作为背景,不能单凭它排除其他资源问题;不过已经明确的文件访问错误应该优先解决。

另一组分支是配置可读但服务提示地址已使用。这个错误指向监听入口冲突,应核对实际占用者和配置端口,再决定修正服务设置,不先终止陌生进程。若日志没有应用错误但内核同时记录了内存终止事件,则进入内存和控制组分支。不要把这三个案例混成一条诊断:它们的触发证据不同,下一步检查对象也不同,采取的恢复动作自然不能相同。

示意日志顺序,仅用于阅读text · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
查询 / 诊断
T0 application: cannot read personal configuration: Permission denied
T1 service manager: main process exited with failure
T2 service manager: scheduled another start attempt

未实机验证的概念示意,不是特定软件保证输出的日志原文。

查看包含普通消息的短时间日志bash · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
查询 / 诊断
journalctl --no-pager -u personal-app.service --since "15 minutes ago" -o short-iso -n 100

read:不只筛选 error,保留故障前后的普通启动消息。

内存看可用量与趋势,不只看空闲量

内核会利用内存缓存文件内容,所以空闲量很小并不自动说明内存不足。先看 MemAvailable 这样的可用量估计,再结合交换空间、应用延迟和一段时间内的变化。单次数据只能说明采样时刻,不能凭一次 VmRSS 增长就判定泄漏。构建任务在读取依赖、打包和压缩阶段有峰值,应记录相同工作负载下的趋势与是否能回落。

VmSize 是虚拟地址空间,不等于实际占用物理内存;VmRSS 也包含可能与其他进程共享的部分,简单相加会误导。系统内存报告还不能直接代表容器额度。若应用异常退出,先查看日志是否给出内存相关原因,而不是把退出码或一句 killed 当作完整结论。不要通过清理内核缓存来制造一个看起来舒服的数字,它可能让后续读盘更慢。

查看系统内存快照bash · Linux(/proc、cat)
查询 / 诊断
cat /proc/meminfo

重点阅读 MemAvailable、MemFree、Cached、SwapFree;这些字段是内核统计,不是某个容器独享的内存额度。 示意:MemAvailable: 2048000 kB;只是采样时估计的可用内存。 字段因内核版本不同而变化;无 /proc 时先确认环境。不能把 MemFree 小直接判定为泄漏,也不能据此清缓存。

容器限制可能先于宿主内存耗尽

宿主尚有空闲内存时,受限的容器仍可能触及自己所在 cgroup 的额度。先根据进程所属 cgroup 确认实际层级,再在有访问权的环境里核对对应控制器统计。cgroup v1 与 v2 文件布局不同,容器内还可能隐藏宿主路径,所以不能把网络文章中的某个固定 memory 路径直接套到本机。本文仅给出定位分组的读取命令。

对 v2 环境,memory.current、memory.max 和 memory.events 可以帮助把当前使用、上限与事件联系起来,但需要读取正确分组,并结合父级约束理解。出现 oom_kill 变化是有用线索,仍应关联发生时间与具体工作负载。后续调整上限属于配置变更,要同时确认宿主余量与并发量;不能只把额度改大而忽略进程泄漏或异常输入。

定位进程所在 cgroupbash · Linux(/proc、cat)
查询 / 诊断
cat /proc/12345/cgroup

以自己的实际 PID 替换 12345;cgroup v2 中 0:: 后面是进程分组路径,可继续按实际挂载布局核对 memory.current、memory.max、memory.events。 示意:0::/user.slice/example.scope;v1 可有多行控制器路径。 容器中路径可能以 / 为根而隐藏宿主层级;不存在或权限拒绝时回到运行环境界面,不能猜路径写入控制文件。

内存分支要比较同一工作负载下的证据

如果错误表现为运行一段时间后被终止,先对齐进程退出时间、内核事件和控制组统计,而不是只看当前系统空闲内存。宿主仍有余量时,某个服务分组可能已触及上限;反过来,分组的当前使用量在进程退出后会下降,事后快照也可能错过峰值。记录发生之前和之后的同类采样、当时执行的任务及并发数量,才能判断是特定大输入、重复任务叠加还是长期增长。

在确认为统一控制组版本的系统中,定位服务所在分组,再按实际挂载位置读取内存用量、上限与事件。父分组限制也可能影响子服务,容器视图还可能隐藏上层,所以本篇不提供假定固定路径的一键读取脚本。事件计数是累计值,看到非零并不能单独确定本次故障;要比较前后增量并对应时间。若没有足够权限读取,记录这一证据缺口,通过已有服务监控或受支持界面补齐,不把缺少输出写成没有限制。

如果确认问题来自一次异常大的个人构建任务,下一步可以是在应用层减少并发或缩小输入,再进行同样任务的有限对照;如果确认长期增长,记录多个可比时间点并检查应用自身诊断能力。调整额度属于运行配置变更,需要同时核对父级和宿主余量。仅把上限提高可能让同一问题稍晚发生,不能成为原因已经解释的证明;修复后的验收仍应覆盖原来触发故障的工作负载。

查询服务所在控制组bash · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
查询 / 诊断
systemctl show personal-app.service --property=ControlGroup

read:据实际输出定位;不推断容器外的挂载路径,不写控制文件。

把恢复动作与原因判断分开

内核日志适合寻找本次启动中的 I/O、设备和内存告警,但筛选 warning 会漏掉较低优先级的信息,日志缺失也无法排除硬件问题。如果是磁盘读写错误,应优先保护已有副本并减少重复负载;如果只是应用端口无响应,则把进程证据与网络诊断结合。不要把所有故障都归到内存,也不要把重启后的暂时恢复当作原因已经解决。

必须恢复服务时,先记录最小现场,再通过服务所属平台的受支持方式执行受控操作。本文不提供默认强杀、清日志或删除内核缓存命令,因为它们容易抹掉证据或放大损害。验收至少包括服务状态、真实功能请求与错误是否再次出现,并注明观察时长。一次请求成功只证明当时可用,持续故障仍需保留后续追踪记录。

查看本次启动内核告警bash · Linux(systemd-journald)
查询 / 诊断
journalctl --no-pager -k -b -p warning -n 100

-k 选内核,-b 选本次启动,-p warning 包含 warning 及更严重级别,-n 限制条数。 示意:可能看到 I/O 或内存相关告警;具体文字依驱动和内核而异。 受日志权限与保存策略影响;空输出不能排除 OOM 或硬件故障。出现 I/O 错误先保护数据,不反复重启测试。

修正以后做一次有边界的恢复验收

在已确认根因并完成必要修正后,按这个个人服务的维护约定恢复运行。若修改了服务单元文件,需要先让管理器重新读取配置;如果只修改应用自己读取的配置文件,则是否支持重新加载取决于应用,不要自动套用管理器重载。下面命令仅针对已经确认的系统级个人单元;所需授权应通过本机既有方式取得,本文不默认添加提权参数,也不在 DSM 上套用这些命令。

重新启动可能中断已有进程,因此先保留故障现场并确认维护窗口。启动后查询服务状态与主进程,重复原来的页面请求,再查看这次启动后的日志,确认同类错误没有立即重现。请求地址使用本机示例回环入口,实际端口由自己的配置确定。状态正常但请求失败时回到监听和应用路由层,不连续重启;请求成功但错误仍持续出现时记录频率,不能把一次成功遮住间歇性故障。

报告结尾分开写“功能已恢复”和“原因已确认”。前者需要真实请求与观察时间,后者需要错误、配置差异与修正后的对照关系。如果只是重启后暂时恢复,应明确根因仍待查,并保留下一次采样所需字段。收尾不删除日志、不清缓存、不清理失败状态来美化界面;这些动作不能增加已有证据。写明未验证长时间负载、下次宿主启动和其他入口,让维护记录保持可重复且不超出本轮范围。

示意故障报告:触发点是移动个人配置目录后再次启动;现象是服务退出、页面无法连接;初步证据为应用先报告配置读取失败;核对对象为服务身份和新父目录穿越权限;修正对象仅为确认错误的那一层目录共享关系;恢复验收回到原页面并检查同类日志。报告不填写虚构权限值,因为真实用户关系未知,必须先检查再决定。这份已明确对象和顺序的记录可以直接用于自己的相同类型事件。

仅修改单元文件后重新读取定义bash · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
会修改状态
systemctl daemon-reload

write:重新读取管理器单元配置;不等于重启应用,仅在确有单元变更时使用。

在维护窗口恢复指定个人服务bash · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
高风险操作
systemctl restart personal-app.service

danger:中断并重新启动该服务;只在已确认单元及修正方案后执行。

重复原来的本机功能请求bash · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
查询 / 诊断
curl --noproxy '*' --fail --show-error --connect-timeout 3 --max-time 10 http://127.0.0.1:18080/

read:端口为示意,换成已确认的个人只读入口;查询成功不能替代后续观察。

已填写的示意材料text · GNU/Linux;macOS/BSD 与 DSM 不直接套用 GNU 长选项
查询 / 诊断
示意时间线(不是实测)
T0 移动配置目录
T1 应用报告 Permission denied
T2 服务启动失败
T3 对照服务身份与目录权限,确认不匹配
T4 按原共享意图修正后受控启动
T5 同入口请求与短窗口日志验收

阅读用示意材料;不是命令输出或实测记录,复制保存为记录文件属于 write。

延伸阅读

Linux kernel:/proc 文件系统 Linux kernel:cgroup v2 systemd 官方源码手册:systemctl systemd 官方源码手册:journalctl curl 官方选项手册 GNU Coreutils 官方镜像:完整手册源码
同一专题 · 继续阅读Linux 文件与权限:从找到文件到安全归档Linux 网络排错:按监听、DNS、HTTP、SSH 分层判断Linux 磁盘与传输:分清容量、inode 和 rsync 复制语义查看整个专题 ↗