简介
运行中的 Linux 系统不只是文件的集合。内核负责管理硬件和进程;每条命令都会作为一个带有标识符的进程运行;Shell 则会跟踪前台和后台作业。管理员通常先观察系统状态,再对相关范围最小的进程采取操作。
在本实验中,你将识别操作系统和内核,解读运行时间与平均负载,检查进程关系,按名称查找进程,发送终止信号,练习交互式作业控制,解读退出状态,使用 nohup 运行脱离终端的命令,并读取最近的内核消息。
识别系统并解读负载
在本步骤中,你将识别内核和发行版,检查系统已运行的时间,并了解平均负载的含义。
创建并进入工作目录:
mkdir -p /home/labex/project/process-lab
cd /home/labex/project/process-lab
uname 命令用于报告内核信息。选项 -s、-r 和 -m 分别选择内核名称、内核发行版号和机器架构:
uname -srm
uname -a 会在一行中显示所有可用字段:
uname -a
内核和 Linux 发行版不是同一个概念。读取发行版元数据:
cat /etc/os-release
查找 NAME、VERSION 和 ID 等字段。接下来,检查系统运行时间和负载:
uptime
输出中包含当前时间、系统已运行的时间、已登录用户数,以及三个平均负载值。这些平均值描述大约在 1 分钟、5 分钟和 15 分钟内处于可运行状态或不可中断状态的工作量。它们不是百分比,具体含义还与 CPU 核心数有关。
查看内核记录的简要负载信息:
cat /proc/loadavg
前 3 个值体现平均负载。后面的字段显示可运行任务数量和最近分配的进程 ID。
保存一份简要系统摘要,供后续参考:
uname -srm > system-summary.txt
uptime >> system-summary.txt
cat system-summary.txt
该文件应包含一行内核信息和一行运行时间信息。
检查进程和资源活动
在本步骤中,你将检查进程标识符、父进程关系和进程状态,并查看系统资源活动的快照。
进程就是正在运行的程序。每个进程都有一个进程 ID,即 PID。大多数进程还有一个父进程 ID,即 PPID,用于标识启动它们的进程。
ps 命令用于显示进程快照。选择需要的字段,并按 PID 排序:
cd /home/labex/project/process-lab
ps -eo pid,ppid,user,stat,comm --sort=pid | head -n 15
选项 -e 选择所有进程,-o 定义要显示的列:
PID表示进程标识符。PPID表示父进程标识符。USER表示进程所有者。STAT表示进程状态以及可选标志。COMMAND表示可执行文件名称。
常见状态字母包括:R 表示运行中,S 表示可中断睡眠,D 表示不可中断睡眠,T 表示已停止,Z 表示僵尸进程。处于睡眠状态的进程通常只是正在等待工作。
BSD 风格的 ps aux 形式会提供 CPU 和内存列,以及完整的命令行:
ps aux | head -n 10
交互式运行 top 时,它会持续更新。批处理模式只生成一个稳定的快照:-b 选择批处理输出,-n 1 请求更新一次。
top -b -n 1 | head -n 12
输出头部会汇总运行时间、平均负载、任务状态、CPU 使用情况和内存使用情况。下面的进程表可以帮助你定位正在消耗资源的进程。
现在打开交互式显示:
top
观察数值更新,找到 %CPU 和 %MEM 列,然后按 q 返回 Shell。需要随时间观察变化时,交互式 top 很有用;需要保存输出或交给其他命令处理时,批处理模式更合适。
保存一份重点进程快照,作为可观察的结果:
ps -eo pid,ppid,user,stat,comm --sort=pid > process-snapshot.txt
head -n 5 process-snapshot.txt
启动并查找练习进程
在本步骤中,你将启动一个无害的后台进程,记录它的 PID,并分别使用 ps 和 pgrep 查找它。
末尾的 & 会让 Shell 在后台运行命令,并立即返回命令行提示符。启动一个运行 5 分钟、可见名称为 labex-worker 的 sleep 进程:
cd /home/labex/project/process-lab
bash -c 'exec -a labex-worker sleep 300' &
特殊 Shell 值 $! 包含最近启动的后台进程的 PID。请在启动另一个后台命令前保存它:
worker_pid=$!
echo "$worker_pid" > worker.pid
准确检查该进程。选项 -p 按 PID 选择进程,-o 选择字段:
ps -o pid,ppid,user,stat,etime,args -p "$worker_pid"
ETIME 显示已运行时间,ARGS 包含可见的进程名称。使用 pgrep -f 搜索完整命令行;-a 还会打印命令行:
pgrep -af labex-worker
pgrep 输出的 PID 应与 worker.pid 中的 PID 一致。使用精确模式搜索,比对所有名称宽泛匹配的进程执行操作更安全。
使用信号停止进程
在本步骤中,你将使用 SIGTERM 请求进程正常终止,并只对专门设计为忽略该请求的进程使用 SIGKILL。
kill 命令向指定 PID 发送信号。如果没有明确指定信号,它会发送 SIGTERM,即信号 15。SIGTERM 请求进程有序关闭,并给进程留下清理工作的机会。
读取工作进程的 PID 并发送 SIGTERM:
cd /home/labex/project/process-lab
worker_pid=$(cat worker.pid)
kill "$worker_pid"
sleep 1
下面命令预期会出现 ps 失败,这可以证明进程已经结束:
ps -p "$worker_pid" || echo "labex-worker stopped after SIGTERM"
现在启动一个会故意忽略 SIGTERM 的受控进程:
bash -c 'trap "" TERM; exec -a labex-stubborn sleep 300' &
stubborn_pid=$!
echo "$stubborn_pid" > stubborn.pid
给新 Shell 一点时间安装信号处理器:
sleep 1
发送 SIGTERM,短暂等待,然后检查进程:
kill -TERM "$stubborn_pid"
sleep 1
ps -o pid,stat,args -p "$stubborn_pid"
由于该练习进程忽略 SIGTERM,它应该仍然存在。SIGKILL,即信号 9,无法被捕获或忽略。只有在正常终止信号不起作用时,才使用它:
kill -KILL "$stubborn_pid"
回收已经终止的后台作业。此时出现非零状态是预期行为,因此 || true 可以让练习流程继续:
wait "$stubborn_pid" 2>/dev/null || true
ps -p "$stubborn_pid" || echo "labex-stubborn required SIGKILL"
SIGKILL 不会给进程保存状态或正常释放应用程序资源的机会,因此它是最后手段。
kill 适用于目标 PID 已知的情况。如果需要按进程名称或完整命令行选择进程,可以使用 pkill,它会结合匹配和发送信号的操作。再启动一个命令行具有明显特征的受控进程:
bash -c 'exec -a labex-helper sleep 300' &
helper_pid=$!
echo "$helper_pid" > helper.pid
执行操作前,确认完整命令行匹配准确:
pgrep -af '^labex-helper 300$'
使用 pkill -f 向准确匹配的进程发送 SIGTERM。锚点 ^ 和 $ 可以避免此练习模式匹配到无关的命令行:
pkill -TERM -f '^labex-helper 300$'
wait "$helper_pid" 2>/dev/null || true
ps -p "$helper_pid" || echo "labex-helper stopped by pkill"
使用精确的 pkill 模式,并先用 pgrep 检查匹配结果;宽泛的模式可能会停止超出预期的进程。
控制前台和后台作业
在本步骤中,你将暂停一个前台命令,将它恢复到后台,再将它切回前台,最后中断它。
作业控制属于当前交互式 Shell。启动一个名称容易识别的前台 sleep 进程:
cd /home/labex/project/process-lab
bash -c 'exec -a labex-job sleep 300'
此时终端被前台进程占用。按 Ctrl+Z。Shell 会发送停止信号并返回命令行提示符。
列出当前 Shell 知道的作业。选项 -l 会包含进程 ID:
jobs -l
你应该会看到一个状态为 Stopped 的作业。在后台恢复作业编号 1:
bg %1
jobs -l
此时状态应变为 Running,并且命令行提示符仍然可用。将该作业切回前台:
fg %1
按 Ctrl+C 向前台作业发送中断信号。命令行提示符应重新出现。确认没有练习作业残留:
pgrep -af labex-job || echo "No labex-job process remains"
完成交互式流程后,创建一个完成标记:
touch job-control.done
对于连接到当前终端的命令,使用作业控制。稍后你将使用 nohup 运行不依赖终端会话的任务。
读取退出状态并运行脱离终端的任务
在本步骤中,你将解读命令退出状态,并运行一个短暂的后台任务,使其输出不依赖终端显示而保留下来。
每条命令都会返回一个整数状态。零表示成功;非零值表示某种失败。Shell 变量 $? 包含刚刚结束的命令的状态。
运行一个成功的命令,然后立即打印它的状态:
cd /home/labex/project/process-lab
true
echo "true status: $?"
结果是 0。现在运行一个找不到路径的命令:
ls missing-path
在其他命令替换 $? 之前保存它的状态:
missing_status=$?
echo "missing-path status: $missing_status"
该值应为非零值。保存这两种预期解释:
printf 'success=0\nfailure=%s\n' "$missing_status" > exit-status.txt
nohup 命令会让程序忽略终端挂起信号。末尾的 & 会在后台启动该程序。重定向 < /dev/null 会断开终端输入,而 > nohup.log 2>&1 会将两个输出流都发送到日志文件:
nohup bash -c 'for item in one two three; do echo "background: $item"; sleep 1; done' < /dev/null > nohup.log 2>&1 &
保存后台进程的 PID,并等待这个短任务完成:
echo $! > nohup.pid
sleep 4
cat nohup.log
你应该会看到 3 行,内容从 background: one 到 background: three。对于长时间运行的任务,保存的 PID 和日志可以帮助你检查进度。
检查最近的内核消息
在本步骤中,你将检查内核消息缓冲区,并保存当前运行的内核版本作为稳定参考。
内核会在环形缓冲区中记录启动、硬件、驱动程序和运行时事件相关的消息。dmesg 会读取该缓冲区。通常需要管理员权限:
cd /home/labex/project/process-lab
sudo dmesg | tail -n 10
具体消息会因机器和时间而异。重点关注类似时间戳的字段,以及生成每条消息的组件或子系统。
选项 --level 可以按严重级别筛选消息。显示最近的警告和错误:
sudo dmesg --level=err,warn | tail -n 10
没有输出不代表命令失败;这可能表示当前缓冲区中没有这些严重级别的消息。搜索最近消息中的常见存储和网络术语:
sudo dmesg | grep -Ei 'disk|filesystem|network|eth' | tail -n 10
同样,结果取决于当前系统。保存 uname -r 报告的内核版本:
uname -r > kernel-version.txt
cat kernel-version.txt
内核消息是证据,不会自动给出诊断结论。在决定采取什么操作前,应将它们与进程状态、服务日志和观察到的症状结合起来分析。
总结
你识别了 Linux 系统,解读了运行时间和平均负载,并使用快照工具和交互式工具检查了进程 ID、父进程、所有者、状态以及资源活动。你启动并查找了指定名称的进程,使用 kill 和 pkill 精确定位目标,先使用 SIGTERM 再使用 SIGKILL,并练习了前台和后台作业控制。
你还解读了退出状态,使用 nohup 和明确的日志记录运行了脱离终端的任务,并使用 dmesg 检查了内核消息。这些先观察再操作的习惯,是安全排查进程问题的基础,也为后续课程中的服务、日志和网络诊断做好准备。



