Linux 软件包管理与服务控制:apt、源码编译与 systemd 实战
软件包管理与服务控制:apt、源码编译与 systemd 一篇讲透
运维学习路线系列 · 阶段一 Linux 地基 · 第 5 篇
适用环境:Ubuntu 24.04 LTS(附 CentOS Stream 9 的 dnf 对照),普通用户(有 sudo)
阅读前提:《S1-01》~《S1-04》
前言:“服务起了但没完全起”
新人部署完 MySQL,mysql能连上就宣布胜利。三天后服务器重启,网站挂了——mysql连不上。上机器一看:
ps-ef|grepmysql# 空的装了 ≠ 在跑,在跑 ≠ 开机自启。软件从"装上"到"可靠运行",中间隔着包管理和服务管理两整套体系。这篇把这两件事一次讲完:上半场 apt 装软件,下半场 systemctl 管服务——下半场是生产核心,systemctl是运维敲得最多的命令之一。
一、上半场:apt 装软件
1.1 apt 四板斧
sudoaptupdate# 刷新索引(装任何东西前先跑,否则可能装到旧版)sudoaptinstallnginx-y# 安装sudoaptremove nginx# 卸载(留配置)sudoaptpurge nginx# 卸载 + 删配置(排错重装时用 purge 才干净)aptlist--installed|grepnginx# 查已装aptshow nginx# 看包信息、版本、依赖aptsearch redis# 搜包名sudoaptupgrade# 升级所有可升级包(不动依赖关系)
update和upgrade的区别背死:update 是"更新目录",upgrade 是"更新商品"。忘了 update 直接 install,可能装到几个月前的仓库快照。
1.2 软件源与国内加速
源配置在/etc/apt/sources.list和/etc/apt/sources.list.d/。Ubuntu 24.04 起是 deb822 格式(.sources文件)。国内机器换源示例:
# 备份后编辑 /etc/apt/sources.list.d/ubuntu.sources,将 archive.ubuntu.com 换成# mirrors.tuna.tsinghua.edu.cn 或 mirrors.aliyun.com,然后:sudoaptupdate1.3 dnf 对照表(CentOS Stream 9)
| 操作 | Ubuntu (apt) | CentOS (dnf) |
|---|---|---|
| 刷索引 | apt update | dnf makecache(多数操作自动做) |
| 装 | apt install nginx | dnf install nginx |
| 卸(含配置) | apt purge nginx | dnf remove nginx |
| 升级 | apt upgrade | dnf upgrade |
| 已装列表 | dpkg -l | rpm -qa |
| 查文件属于哪个包 | dpkg -S /usr/bin/nginx | rpm -qf /usr/bin/nginx |
| 装某个文件缺的库 | 自动 | dnf provides "*/libssl.so.3" |
1.4 源码编译:什么时候才需要
90% 的场景用包管理就够。只有包版本太老(比如需要新特性)、或公司要求自定义编译参数时才上源码三步曲:
# ① 装编译依赖sudoaptinstall-ybuild-essential libpcre2-dev zlib1g-dev libssl-dev# ② 经典三步曲(以 nginx 为例)./configure--prefix=/opt/nginx --with-http_ssl_module# 检查环境 + 生成 Makefilemake-j$(nproc)# 编译sudomakeinstall# 安装到 /opt/nginx🚨 源码编译的代价:不会自动生成 systemd 服务、升级要重编、卸载没有登记——所以编译安装后第一件事就是手写 service 文件(下半场教你)。
二、下半场:systemd 服务管理
2.1 为什么是 systemd
开机后谁来把 nginx、mysql 一个个拉起来?谁来在它们挂掉时重启?谁来管依赖顺序(网络就绪再起应用)?——现代 Linux 的答案都是systemd(PID 1)。它管的东西叫"单元(unit)",服务是.service、定时器是.timer(第 8 篇见)、挂载是.mount。
2.2 systemctl 全生命周期速查
# ── 状态 ──────────────────────────────systemctl status nginx# 状态总览(排错第一命令!)systemctl is-active nginx# 输出 active/inactive,脚本里用它判断systemctl is-enabled nginx# 是否开机自启systemctl list-units--type=service--state=running# 当前所有运行中的服务systemctl list-unit-files--type=service# 全部服务与自启状态systemctl--failed# 挂掉的服务(巡检必跑)# ── 控制 ──────────────────────────────sudosystemctl start nginx# 启动sudosystemctl stop nginx# 停止sudosystemctl restart nginx# 重启(有中断!)sudosystemctl reload nginx# 重读配置不断服务(nginx/mysql 都支持,优先用它)sudosystemctlenablenginx# 开机自启(不影响当前状态)sudosystemctl disable nginx# 取消自启# ── 组合技 ───────────────────────────sudosystemctlenable--nownginx# 自启 + 立即启动,一条搞定sudosystemctl daemon-reload# 改过 unit 文件后必须执行才生效💡排错金句:服务起不来,别猜,三连——
systemctl status xxx(看主 PID 与报错摘要)→journalctl -u xxx -n 50(看该服务日志)→ss -lntp(端口到底被谁占了)。三个命令覆盖 80% 的"服务异常"。
2.3 status 输出怎么读
● nginx.service - A high performance web server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; ...) └─ unit 文件路径;enabled = 开机自启 ✅ Active: active (running) since Tue 2026-10-20 14:00:08 CST; 3h ago └─ active(running) 才是真在跑;后面是启动时间 Main PID: 1234 (nginx) └─ 主进程号,ps 交叉验证用 Tasks: 3 Memory: 5.2M CGroup: /system.slice/nginx.service ├─1234 nginx: master process └─1235 nginx: worker process ← 子进程全在这,杀干净可看这里🚨enabled和active是两码事:enabled 只代表"开机会拉起",不代表现在在跑;反过来 active 也不代表 enabled——"现在活着的、重启后会死"的服务是最大的隐患,巡检务必两个都查。
2.4 写一个自己的 service 文件
场景:编译安装的 nginx,或自己写的 Python 服务要"挂了自动拉起 + 开机自启"。
# /etc/systemd/system/myapp.service [Unit] Description=My Flask App After=network.target # 依赖:网络就绪后再启动 [Service] Type=simple # 主进程不 fork,最常见 User=deploy # 🚨 别用 root 跑业务! WorkingDirectory=/data/app ExecStart=/data/app/venv/bin/python app.py Restart=always # 挂了就拉(异常退出) RestartSec=3 Environment="PORT=8080" # 环境变量写这里,别写进 /etc/environment [Install] WantedBy=multi-user.target # 固定写法,enable 的锚点sudosystemctl daemon-reloadsudosystemctlenable--nowmyapp systemctl status myapp💡
Restart=always+RestartSec就是生产里最朴素的"自愈",配合阶段四的监控告警,才敢说"服务有人管"。
三、🚨 避坑清单
| # | 坑 | 后果 | 正确姿势 |
|---|---|---|---|
| 1 | 装完服务没enable | 机器重启全站下线 | 部署清单固定含enable --now |
| 2 | 分不清 active / enabled | “明明在跑怎么重启就没了” | 巡检两态都查:is-active+is-enabled |
| 3 | 改了 unit 文件不daemon-reload | 改动完全不生效,以为"配置玄学" | 改完必跑 |
| 4 | 用service/旧命令混着敲 | 行为不一致(部分是兼容层) | 统一 systemctl |
| 5 | 业务进程用 root 跑 | 被打穿就是 root 权限 | unit 里User=www-data |
| 6 | 需要"重载配置"却用了 restart | 无谓的中断 | 支持 reload 的服务优先reload |
| 7 | 编译装完不写 service | 挂了没人拉、重启不自动起 | 三步曲之后第 4 步写 unit 文件 |
| 8 | apt purge重装时留了数据目录 | “重装也没解决” | 数据目录(如 /var/lib/mysql)单独确认后处理 |
四、一句话总结
apt 负责"装得下",systemctl 负责"活得久"——部署完任何服务,status确认 active、is-enabled确认自启,才算交付完成。
💬 互动
你有没有经历过"服务器重启后服务全没起来"的早晨?或者 service 文件写了半天不生效,最后发现是忘了 daemon-reload?评论区见。
下一篇预告:《S1-06 Linux 进程管理:ps、top、kill、nohup 与信号》——服务"活着"之后,怎么看清它、控制它、以及为什么 kill -9 要慎用。