🐧 第04章 · 服务与进程管理
systemctl ps kill
服务与进程管理¶
服务器上跑着的一堆东西,要么是受 systemd 托管的"服务",要么是临时发作的"进程"。这一章讲清 Systemd 服务管理(systemctl)与进程管理(ps/kill)两套工具,以及本机 Node 应用、Nginx、MySQL 的日常管理。
进程 vs 服务¶
- 进程 (Process) —— 一个运行中的程序,有 PID,是
ps/kill管理的对象; - 服务 (Service) —— 受 systemd 托管的常驻进程,有 unit 名,是
systemctl管理的对象。
两者关系:一个服务往往就是一个进程(或多进程)。本机 bangdream.service 底层就是那个 Node 进程。
服务管理:systemctl¶
Systemd 是 Ubuntu 24.04 的 init 系统,PID 1。systemctl 是最常用命令:
| 命令 | 作用 | 示例 |
|---|---|---|
systemctl status <u> |
查看状态与最近日志 | systemctl status nginx |
systemctl start <u> |
启动 | systemctl start nginx |
systemctl stop <u> |
停止 | systemctl stop nginx |
systemctl restart <u> |
重启 | systemctl restart bangdream |
systemctl reload <u> |
重载配置(不中断连接) | systemctl reload nginx |
systemctl enable <u> |
开机自启 | systemctl enable nginx |
systemctl disable <u> |
取消开机自启 | systemctl disable nginx |
systemctl is-active <u> / is-enabled <u> |
立即显示 active/enabled | systemctl is-active mysql |
systemctl status bangdream # 看状态+最近几行日志,最常用
systemctl restart lovelive # 重启 Node 服务
systemctl enable --now nginx # 开机自启并立即启动(-now 一步到位)
systemctl list-units --type=service --state=running | head # 列出正在运行的服务
易错 修改了 unit 文件(
/etc/systemd/system/xxx.service)后必须systemctl daemon-reload重载,否则新配置不生效,很多人改完发现没效果就是漏了这一步。
开机自启管理¶
服务是"现在启动"还是"开机启动",是两个独立状态,用 is-active/is-enabled 分别看:
systemctl is-enabled nginx # enabled / disabled / static
systemctl is-active nginx # active / inactive
systemctl list-unit-files | grep -E "nginx|mysql|bangdream" # 列出含这些字的 unit 及自启状态
systemctl mask bash.service # 彻底禁用一个服务(rename 到 /dev/null,比 disable 更硬)
易错
enable只设置开机自启,不会立即启动;要既自启又立刻跑,用enable --now。mask和disable不同:mask会把 unit 链接到/dev/null,任何人调 start/restart 都无效,适合"永久禁掉易冲突的服务"。
服务的配置文件在哪¶
- 系统自带:
/lib/systemd/system/(apt 装的); - 管理员自建:
/etc/systemd/system/(你或程序装的); - 查看:
systemctl cat <u>。
systemctl cat bangdream # 一键看 unit 文件位置与内容
本机 Node 服务的 unit 大概形如:
[Service]
ExecStart=/usr/local/bin/node server.js
WorkingDirectory=/var/www/bangdream
Restart=on-failure
Restart=on-failure 说明进程崩溃会自动拉起,这是生产服务的标配——这也是 Node 应用崩溃后"自己又活了"的原因。
进程查看:ps 与 top¶
ps 是静态快照:
ps aux # 列出所有进程(BSD 风格,-aux 三参数)
ps -ef # 列出所有进程(System V 风格,-e -f)
ps aux | grep nginx # 过滤出含 nginx 的行
# 按 PID 找进程,或反转
ps -p $(pgrep nginx) -o pid,cmd # pgrep 找 PID 再取详情
pgrep -af node # 列出所有 node 进程及其完整命令行
pidof node # 输出 node 的 PID(可能多个)
top 是实时视图,前面已介绍;htop 是它的彩色增强版(需安装):
htop # 彩色进程列表,可 F5 看进程树,F9 kill
结束进程:kill 与信号¶
进程间用"信号"通信,kill 发送信号:
| 信号 | 编号 | 含义 | 适度 |
|---|---|---|---|
TERM |
15 | 请求优雅退出 | 常规推荐,先给进程自我清理的机会 |
KILL |
9 | 强制杀死 | 兜底,进程无法清理就立即消失 |
HUP |
1 | 重载配置/日志 | 部分服务用它 reload |
kill <pid> # 默认 15,优雅结束
kill -9 <pid> # 强制杀死(有风险)
kill -HUP <pid> # 通知进程重载配置
pkill -f "node server.js" # 按命令行模式匹配杀(f 用整条命令匹配)
killall node # 按进程名杀(会杀所有 node,慎用)
易错 先给
kill(TERM 15),不要上来就kill -9。TERM 允许进程保存状态、释放资源;-9会跳过清理,可能导致数据库/文件系统不一致。若 TERM 几秒不退再kill -9。
查找占用端口的进程¶
服务起不来、端口被占,从端口反查进程最直接:
ss -tlnp | grep 3000 # 谁在监听 3000(本机是 bangdream 的 Node)
ss -tlnp | grep 3306 # MySQL
ss -tlnp | grep 10086 # Xray
lsof -i :8090 # GitLab 反代端口(需安装 lsof)
易错
ss/lsof查端口需要 root 才能显示进程名,用普通用户只看得到端口看不到 PID。ss -tlnp的-l只显示监听、-tTCP、-n不解析域名、-p带进程。
后台任务与 nohup¶
手动跑脚本(如本机 cron 里的 tieba_sign.py)想放后台:
nohup /usr/bin/python3 /root/scripts/tieba_sign.py > /var/log/tieba.log 2>&1 &
# nohup 忽略 SIGHUP(关终端不杀);& 放后台;> log 重定向输出
jobs # 查看当前 shell 的后台任务
disown %1 # 让后台任务不受 shell 退出影响
易错
nohup+&是老式做法,生产上优先用 systemd service(能自启、能崩溃重启、开机拉起)。cron 里的任务用输出重定向>> log 2>&1保存日志,否则任务输出会被 cron 邮件吞掉。
案例:端口 3000 被占,bangdream 起不来¶
ss -tlnp | grep 3000 # 先看谁占用
pid=$(lsof -t -i:3000) # 拿到占用的 PID
kill $pid # 优雅结束
systemctl start bangdream # 再启动
易错点¶
- 改完 unit 不
daemon-reload:新配置不生效。 enable不等于立即启动:用enable --now。- 上来就
kill -9:先kill(TERM)让进程优雅退出。 - 以普通用户
ss查不到进程名:用 root。
相关命令¶
systemctl、ps、pgrep、pidof、top、htop、kill、pkill、killall、ss、lsof、nohup、jobs。