进程基础概念
进程(Process)
程序运行时的实例。每个进程有唯一的 PID(Process ID),拥有独立的内存空间、打开的文件、信号处理器等。Linux 用树状结构组织进程,所有进程都是 PID=1 的 init/systemd 的后代。
父进程与子进程
Shell 执行命令时,会 fork() 出子进程来运行该命令。子进程的 PPID(Parent PID)指向父进程。父进程等待子进程退出并回收其退出状态。若父进程先退出,子进程变为"孤儿进程",被 systemd(PID=1) 收养。
进程状态
R(Running/Runnable):运行或等待运行;S(Sleeping):可中断睡眠,等待事件;D(Disk Sleep):不可中断睡眠,等待 I/O;Z(Zombie):已退出但父进程未回收;T(Stopped):被信号暂停;I(Idle):空闲内核线程。
前台与后台进程
前台进程占用终端,用户等待其完成;后台进程在后台运行,终端立即返回提示符。使用 & 符号将命令放入后台,使用 jobs/fg/bg 管理。
查看进程:ps 命令
# BSD 风格(最常用)
ps aux # 显示所有用户的所有进程(详细信息)
ps aux | grep nginx # 查找 nginx 相关进程
ps aux --sort=-%cpu # 按 CPU 使用率排序(降序)
ps aux --sort=-%mem # 按内存使用率排序
# UNIX 风格
ps -ef # 显示所有进程(包含 PPID)
ps -ef | grep java
ps -u alice # 只显示 alice 的进程
# 进程树
ps auxf # ASCII 树状图显示进程关系
pstree # 更直观的树状图
pstree -p # 显示 PID
pstree -u # 显示用户名
# 查看特定进程
ps -p 1234 # 查看 PID=1234 的进程
ps -p 1234 -o pid,ppid,cmd,rss,vsz # 自定义输出列
ps aux 列含义:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
alice 1234 2.5 1.2 55420 9820 pts/0 Sl 10:00 0:05 python app.py
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ └─ 累计 CPU 时间
│ │ │ │ │ │ │ └─ 启动时间
│ │ │ │ │ │ └─ 进程状态
│ │ │ │ │ │─ 终端
│ │ │ │ └─ 实际物理内存 (KB)
│ │ │ └─ 内存使用 %
│ │ └─ 虚拟内存大小 (KB)
│ └─ CPU 使用 %
└─ 进程 ID
实时监控:top 与 htop
# top:系统自带的实时监控工具
top # 默认按 CPU 使用率排序
top -u alice # 只显示 alice 的进程
top -p 1234,5678 # 监控特定 PID
top -b -n 1 # 批量模式,输出一次后退出(用于脚本)
top -b -n 1 | head -20 # 取前20行
# top 快捷键(运行中按键)
# k 按 PID 终止进程
# r 修改进程优先级(renice)
# M 按内存排序
# P 按 CPU 排序(默认)
# T 按运行时间排序
# 1 展开/折叠 CPU 核心
# q 退出
# htop:功能更强大的交互式监控(需要安装)
apt install htop
htop
htop -u alice # 只显示 alice 的进程
htop -p 1234 # 监控特定 PID
top 头部信息解读
- load average: 0.52, 0.38, 0.30:最近 1/5/15 分钟的平均负载。负载 = CPU 核心数时代表满负荷,超过核心数则过载
- %us, %sy, %ni, %id, %wa:用户态/内核态/nice调整/空闲/IO等待 CPU 占比
- Mem: total, free, used, buff/cache:物理内存;buff/cache 可被回收,实际可用 = free + buff/cache
- Swap:交换分区使用情况,大量 Swap 使用说明内存不足
信号与 kill 命令
常用信号
SIGTERM(15,默认)
请求进程正常退出。进程可以捕获此信号,做清理工作后再退出(关闭连接、保存状态等)。这是最礼貌的终止方式,应该首先尝试。
SIGKILL(9)
强制立即终止进程。内核直接杀死进程,进程无法捕获或忽略此信号,无法做清理工作。用于进程无响应或拒绝退出时。可能导致数据损坏,谨慎使用。
SIGHUP(1)
挂起信号。历史上用于通知进程终端断开。现代用途:通知进程重新加载配置文件,无需重启(nginx、sshd 等都支持 SIGHUP 热重载)。
SIGSTOP(19)/ SIGCONT(18)
暂停/继续进程执行。Ctrl+Z 发送 SIGTSTP(可被捕获的软暂停),SIGSTOP 不可被捕获。SIGCONT 恢复被暂停的进程。
# kill:按 PID 发送信号
kill 1234 # 默认发送 SIGTERM(15)
kill -15 1234 # 显式 SIGTERM
kill -9 1234 # SIGKILL(强制)
kill -1 1234 # SIGHUP(重载配置)
kill -STOP 1234 # 暂停进程
kill -CONT 1234 # 恢复进程
# killall:按进程名发送信号
killall nginx # 终止所有名为 nginx 的进程
killall -9 python3 # 强制终止所有 python3 进程
killall -u alice python3 # 只终止 alice 的 python3 进程
# pkill:按名称模式匹配
pkill -f "python app.py" # 匹配完整命令行
pkill -u alice # 终止 alice 的所有进程
pkill -9 java # 强制终止所有 java 进程
# 查看所有信号
kill -l # 列出所有信号名
# 正确的终止进程流程
# 1. 先尝试 SIGTERM(给进程清理机会)
kill 1234
# 2. 等待几秒
sleep 3
# 3. 检查是否已退出
ps -p 1234 || echo "进程已退出"
# 4. 仍存在则强制终止
kill -9 1234
后台作业管理
# 在后台启动命令(用 & 符号)
./long-running-task.sh & # 返回: [1] 12345(作业号和PID)
python server.py &
# 将前台进程发送到后台
# 1. 按 Ctrl+Z 暂停当前前台进程
# 输出: [1]+ Stopped ./task.sh
bg %1 # 将作业 1 在后台继续运行
bg # 将最近暂停的作业放入后台
# jobs:查看当前 Shell 的后台作业
jobs # 列出所有作业
jobs -l # 显示 PID
# 输出示例:
# [1]- Running python server.py &
# [2]+ Stopped vim notes.txt
# fg:将后台作业调回前台
fg %1 # 将作业 1 调回前台
fg # 调回最近的作业(+ 标记的)
fg %python # 按名称匹配
# 等待后台作业完成
wait %1 # 等待作业 1 完成
wait # 等待所有后台作业
nohup:终端关闭后继续运行
# 问题:SSH 断开后,后台进程会收到 SIGHUP 而终止
# 解决:nohup 让进程忽略 SIGHUP 信号
nohup ./task.sh & # 后台运行,输出到 nohup.out
nohup python server.py > app.log 2>&1 & # 重定向输出
nohup ./deploy.sh > /dev/null 2>&1 & # 丢弃所有输出
# 查看 nohup 进程(新 SSH 会话后)
ps aux | grep task.sh
# 更好的替代方案:screen 或 tmux
screen -S mysession # 创建命名会话
# (在 screen 中运行命令)
# 按 Ctrl+A, D 分离会话
screen -ls # 列出所有会话
screen -r mysession # 重新连接会话
# tmux(更现代的方案)
tmux new -s deploy # 创建名为 deploy 的会话
# 按 Ctrl+B, D 分离
tmux ls # 列出会话
tmux attach -t deploy # 重新连接
进程优先级:nice 与 renice
# Nice 值范围:-20(最高优先级)到 +19(最低优先级)
# 普通用户只能设置 0~19(降低优先级)
# root 可以设置 -20~19
# nice:启动时设置优先级
nice -n 10 ./cpu-intensive-task.sh # 低优先级运行(让出 CPU)
nice -n -5 ./critical-task.sh # 高优先级(需要 root)
# renice:修改运行中进程的优先级
renice -n 15 -p 1234 # 降低 PID=1234 的优先级
renice -n -10 -p 1234 # 提高优先级(需要 root)
renice -n 5 -u alice # 修改 alice 所有进程的优先级
# 查看进程优先级(NI 列)
ps -lo pid,ni,cmd # 显示 nice 值
top # NI 列显示 nice 值,PR 列显示调度优先级
systemctl:系统服务管理
服务的生命周期
# 启动/停止/重启服务
sudo systemctl start nginx # 启动
sudo systemctl stop nginx # 停止
sudo systemctl restart nginx # 重启(先停后启)
sudo systemctl reload nginx # 热重载配置(不中断连接)
# 开机自启动
sudo systemctl enable nginx # 开机自启
sudo systemctl disable nginx # 取消开机自启
sudo systemctl enable --now nginx # 启动并设置开机自启
sudo systemctl disable --now nginx # 停止并取消自启
# 查看服务状态
systemctl status nginx # 详细状态(最近日志、PID、内存等)
systemctl is-active nginx # 输出 active/inactive/failed
systemctl is-enabled nginx # 输出 enabled/disabled
systemctl is-failed nginx # 输出 failed/active
# 列出服务
systemctl list-units --type=service # 所有活跃服务
systemctl list-units --type=service --all # 包含未启动的
systemctl list-units --type=service --state=failed # 失败的服务
# 系统级操作
sudo systemctl reboot # 重启系统
sudo systemctl poweroff # 关机
sudo systemctl suspend # 挂起
sudo systemctl daemon-reload # 重新加载 systemd 配置(修改 Unit 文件后)
创建自定义服务
# 创建 systemd Unit 文件
sudo nano /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/server.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=5
Environment=NODE_ENV=production
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
# 启用并启动自定义服务
sudo systemctl daemon-reload # 重新加载 Unit 文件
sudo systemctl enable --now myapp # 开机自启并立即启动
sudo systemctl status myapp # 查看状态
journalctl:查看系统日志
# 查看所有日志
journalctl # 所有日志(从最早开始)
journalctl -r # 倒序(最新的在前)
journalctl -n 50 # 最新 50 条
journalctl -f # 实时跟踪(类似 tail -f)
# 按服务过滤
journalctl -u nginx # nginx 服务的日志
journalctl -u nginx -f # 实时跟踪 nginx 日志
journalctl -u nginx -n 100 # nginx 最新 100 条
journalctl -u nginx --since today # 今天的 nginx 日志
# 时间过滤
journalctl --since "2024-01-10"
journalctl --since "2024-01-10 10:00" --until "2024-01-10 11:00"
journalctl --since "1 hour ago"
journalctl --since yesterday
# 按级别过滤
journalctl -p err # 错误及以上级别
journalctl -p warning # 警告及以上
journalctl -u nginx -p err # nginx 的错误日志
# 级别:emerg(0) alert(1) crit(2) err(3) warning(4) notice(5) info(6) debug(7)
# 输出格式
journalctl -u nginx --output=json # JSON 格式
journalctl -u nginx --output=cat # 只显示消息文本
# 磁盘空间管理
journalctl --disk-usage # 查看日志占用空间
journalctl --vacuum-time=7d # 删除 7 天前的日志
journalctl --vacuum-size=500M # 保留最近 500MB
服务故障排查流程
systemctl status myapp— 查看当前状态和最近日志journalctl -u myapp -n 50— 查看详细日志journalctl -u myapp -p err— 过滤错误信息- 根据日志信息修复配置文件或代码
systemctl daemon-reload(若修改了 Unit 文件)systemctl restart myapp— 重启服务
本章小结
Linux 进程管理的核心要点:① 进程状态中 D(不可中断睡眠)表示 I/O 等待,大量 D 状态进程说明磁盘/网络存在问题;② kill -9 是最后手段,先用 kill(默认 SIGTERM)给进程清理机会;③ Ctrl+Z + bg 将前台进程转为后台运行,fg 调回前台;④ nohup 让进程在终端断开后继续运行,但更好的选择是 tmux/screen 会话;⑤ systemd 是现代 Linux 的服务管理核心,systemctl enable --now 一步完成启动并设置自启;⑥ journalctl -u 服务名 -f 实时追踪服务日志,-p err 过滤错误级别;⑦ 进程优先级 nice 值范围 -20(最高)到 +19(最低),普通用户只能降低优先级(0-19)。