如果你已经折腾完前面两章,能熟练地用 cd、ls、cp、vim 在 Linux 系统里做基本操作,那恭喜,你已经跨过了“装好系统、能用终端”的第一道坎。但这会儿你大概率有个感觉:一会儿要 sudo,一会儿权限不足,看着 drwxr-xr-x 一脸懵,新建用户也不知道从哪下手,装个软件全是依赖地狱,更别提服务器上跑个服务怎么找问题。
第三章的价值,就是帮你把这些“半懂不懂”的东西彻底焊死。这一章我会从用户体系、文件权限、文本处理与查找、进程与服务、软件安装五个维度,用实际运维中一定会遇到的场景串起来。内容不追求大而全,但要让你学完能真正面对一台“脏乱差”的Linux服务器时,敢动手、知道去哪查、知道为什么这么做。坦白说,跨过这一章,你就从“会用Linux的人”变成了“能管理Linux的人”,这也是面试和实际工作中最明显的一道分水岭。
1. 新建用户与用户组:账户体系是系统管理的第一课
1.1 先搞清楚为什么 Linux 要搞这么多用户
很多人刚接触 Linux 会有一个疑惑:我在自己电脑上装个系统,就我一个人用,为什么还要分用户?这个困惑在你第一次登录云服务器时会被瞬间击碎——因为这台服务器上很可能有十几个账户,有运维的、开发的、跑程序的,甚至还有系统自己创建的 nobody、www-data 这类账户。
Linux 天生就是多用户操作系统,它的设计初衷就是一台机器上同时服务很多人。而这种多用户模型带来的好处是:权限隔离。每个人有自己的家目录、自己的文件、自己的进程,互相看不到,也改不动。这就是整个 Linux 安全模型的根基。我见过不少新手拿到 root 权限后,什么事情都 root 一把梭,结果一条 rm 命令下去,把整个系统的文件删了个七七八八,这种事故在运维圈里不算新鲜。所以学用户管理,第一层意义是理解隔离,第二层意义是保护自己。
1.2 useradd 参数拆解:一次完整的新建用户操作
Linux 新建用户有两个命令,一个是 useradd,一个是 adduser。Debian/Ubuntu 系里 adduser 是一个交互式脚本,会一步步问你密码、全名等;而 useradd 是原生的系统调用命令,所有参数一次性指定,不指定就不会帮你创建家目录。日常脚本化操作和服务器管理,我建议你熟练掌握 useradd。
先看一个完整的示例:
bash复制sudo useradd -m -d /home/zhangsan -s /bin/bash -G wheel zhangsan
sudo passwd zhangsan
这行命令干了四件事:
-m:自动创建家目录 /home/zhangsan,不写这个,用户登录后连 home 都没有;-d:指定家目录位置,默认就是 /home/用户名,但有时你需要把家目录放到数据盘,比如 /data/home/zhangsan;-s:指定登录 shell,/bin/bash 是交互式用户的标配,如果是跑服务用的专用账户,可以用 /usr/sbin/nologin 禁止它登录;-G:把用户加入附加用户组,wheel 组(CentOS/RHEL)或 sudo 组(Ubuntu)代表可以执行 sudo 命令。
如果你是在 Ubuntu 上,-G sudo 而不是 -G wheel,因为不同发行版管理 sudo 权限的组名不一样。这正是很多人踩坑的地方——在 Ubuntu 上给用户加 wheel 组,结果用户并没有 sudo 权限。
1.3 用户信息存在哪里:三份文件的字段逻辑
新建完用户后,我建议你立刻看三个文件,它们就是整个用户体系的“数据库”:
/etc/passwd:保存用户基本信息,一行一个用户,冒号分隔 7 个字段。比如zhangsan:x:1000:1000::/home/zhangsan:/bin/bash,依次是用户名、密码占位符 x、UID、GID、注释信息、家目录、登录 shell。密码那栏显示 x,是因为真正的密码挪到了 shadow 文件。/etc/shadow:保存密码哈希和密码策略。只有 root 能读,字段包括加密后的密码、最近修改时间、最短修改间隔、过期时间等。/etc/group:保存用户组信息。格式是组名:组密码:GID:组成员。
这三个文件一定要记住,因为很多权限问题排查到最后,根源就是这里某个字段写错了。比如 UID 冲突、GID 不存在、shell 路径错误,都会导致用户无法正常登录或无法使用某些功能。
1.4 修改与删除用户时的常见坑
用户建好之后,改信息用 usermod,改密码用 passwd,删除用 userdel。几个实测下来容易出问题的点:
usermod -l newname oldname可以改用户名,但注意家目录和邮箱不会自动跟着改,要手动处理;userdel zhangsan默认不删家目录,会留下一堆垃圾文件;userdel -r zhangsan才连家目录和邮件池一起删。但生产环境务必谨慎,先确认这个用户的文件有没有价值再删;passwd -l zhangsan是锁定账户(在密码前加 !),passwd -u zhangsan解锁。临时禁止用户登录,优先用这个而不是直接删用户。
1.5 用 sudo 而不是永远 root:权限边界与个人习惯
最后想聊聊 sudo。很多初学者不理解,我都有 root 了,为什么还要建普通用户再 sudo?原因有三点:第一,root 的操作不会留下清晰审计记录,出事没法追查;第二,root 的误操作代价被放得极大,一条 rm -rf / 和对普通用户来说影响有限;第三,sudo 可以精细化授权——你可以指定某个用户只能执行 systemctl restart nginx,而不能干别的。
配置 sudo 权限的文件是 /etc/sudoers,修改它一定要用 visudo 命令,因为这个命令会做语法检查,防止你写错导致整个 sudo 瘫痪。常见的配置是 %wheel ALL=(ALL) ALL,意思是 wheel 组的成员可以在所有主机上以所有用户身份执行所有命令。给特定用户指定命令权限可以写成:
bash复制zhangsan ALL=(ALL) /usr/bin/systemctl restart nginx
这样 zhangsan 只能重启 nginx,其他 sudo 命令一律拒绝。这就是最小权限原则在账户体系里的体现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 文件权限的完整拆解:从 drwxr-xr-x 到 SUID/ACL
2.1 从 ls -l 读出的第一个判断:文件类型
ls -l 输出的第一列,比如 drwxr-xr-x,是由 10 个字符组成的。第一个字符代表文件类型,后面 9 个字符是三组权限位。很多教程把这两件事混在一起讲,我建议你先分开记。
第一个字符常见的有:
| 字符 | 含义 | 示例 |
|---|---|---|
| - | 普通文件 | 文本、二进制、日志 |
| d | 目录 | /home、/etc |
| l | 软链接 | /usr/bin/python3 -> python3.11 |
| b | 块设备 | /dev/sda 硬盘 |
| c | 字符设备 | /dev/tty 终端 |
| s | 套接字 | /var/run/docker.sock |
| p | 管道文件 | 用于进程间通信 |
为什么先讲这个?因为你在写脚本、做判断时,文件类型直接决定你要用哪种方式处理它。热搜词里有个“linux指令[-d]”,说的就是 shell 的 test 判断:[ -d /tmp ] 用来判断 /tmp 是不是目录,[ -f /etc/passwd ] 判断是不是普通文件。理解了文件类型的含义,这类命令一看就懂了。
2.2 权限位对文件和目录的不同含义
后面 9 个字符分成三组:所有者(u)、所属组(g)、其他人(o),每组里又是 rwx 三个权限位。这里最核心也最容易被忽略的知识点是:同样的 rwx,对文件和目录的含义完全不同。
对普通文件来说,r 是能读内容,w 是能改内容,x 是能执行(脚本/二进制)。
对目录来说,含义完全变了个样:
- r:能列出目录里的文件名(ls 能看到名字);
- w:能在目录里创建、删除、重命名文件;
- x:能进入目录(cd 进去),能访问目录里文件的具体属性。
所以你会看到一个现象:一个目录就算有 r 权限但没有 x,你 ls 能看到文件名,但 cd 进不去,stat 查看文件详情也会报错。反之有 x 没有 r,能进去但列不出名字,只能凭完整文件名访问。这是面试里特别爱考的一个点。
2.3 chmod、chown、umask:权限修改的三种工具
改权限用 chmod,两种姿势:
- 数字法:r=4,w=2,x=1,权限就是三者之和。
chmod 755 file等于所有者 rwx、组 r-x、其他人 r-x。这是一个最常见的配置,目录和可执行文件基本都用它。 - 符号法:
chmod u+x file给所有者加执行权限,chmod g-w file去掉组的写权限,chmod o=r file把其他人的权限设为只读。符号法适合精确修改,不用重算整个值。
改归属用 chown:
bash复制sudo chown zhangsan:develop /data/project
sudo chown -R zhangsan:develop /data/project
-R 递归修改。有一点想提醒你:不要轻易对整个用户家目录执行 chown -R,尤其是 /home/zhangsan 里如果有软链接,递归修改可能会顺着软链接改到目标文件,搞出权限事故。
umask 则决定了新建文件的默认权限。系统默认 umask 通常是 022,含义是从 666 中减去 022,所以新建普通文件是 644(rw-r--r--),新建目录是 755(rwxr-xr-x)。如果你希望团队协作时新文件默认组内可写,可以把 umask 改成 002,这样文件是 664,目录是 775。
2.4 SUID、SGID、Sticky Bit 三个特殊权限
普通权限之外还有三个特殊权限位,很多系统异常都跟它们有关。
SUID(Set UID)出现在所有者的 x 位上,表现为 s。最典型的例子是 /usr/bin/passwd:
bash复制ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 ...
普通用户修改自己的密码,需要写 /etc/shadow,而 shadow 只有 root 能读写。为什么普通用户能改?就是因为 passwd 程序带 SUID,执行它时,进程临时获得文件所有者(root)的权限。SUID 是双刃剑,一个程序有了它,就相当于给了任何执行者一把 root 的钥匙,所以别随便给脚本加 SUID。
SGID(Set GID)出现在组的 x 位上,同样表现为 s。对目录设置 SGID 后,在该目录下新建的文件会继承目录的所属组,而不是创建者的默认组。这是团队协作目录的标准配置:
bash复制chmod g+s /data/team_project
Sticky Bit 表现为其他人的 x 位变成 t。典型就是 /tmp:
bash复制ls -ld /tmp
drwxrwxrwt 20 root root ...
它的作用是:在 /tmp 里,任何人都能创建文件,但只有文件所有者(或 root)才能删除自己的文件。没有 Sticky Bit,A 用户就能删掉 B 用户放在 /tmp 里的文件,这显然不行。
2.5 实战:一次 nginx 部署中的 Permission Denied 定位
这块内容不是干讲概念。我有一次给客户部署 nginx 静态网站,网站文件放在 /data/www,nginx 配置指向这里,结果访问页面 403,日志里报 Permission denied。
排查过程是这样的:
- 先看进程用户:nginx worker 默认以 www-data 用户运行;
- 再看文件权限:
ls -l /data/www/index.html显示 644,权限没问题; - 继续往上级目录查:
ls -ld /data /data/www,发现 /data 是 750,所有者是 root,组是 root,www-data 对 /data 根本没有 x 权限。x 权限缺失意味着 nginx 进程无法“穿过”这个目录去访问里面的文件。
这就是目录 x 权限的经典场景。修复很简单:chmod o+x /data 或者 setfacl -m u:www-data:x /data。如果你只是盯着文件本身看权限,永远找不到问题。这也是我为什么建议学权限时,必须从文件往根目录一层层看到底。
另外,如果普通权限搞不定,还有个 ACL(访问控制列表)工具可以精确授权:
bash复制setfacl -m u:zhangsan:rw /data/project/config.yaml
getfacl /data/project/config.yaml
ACL 能让某个特定用户对某个文件有指定权限,而不改文件属主,这在多团队共用服务器时非常实用。
3. 查找、清理与文本处理:find、rm 和管道组合的实战
3.1 find 的核心语法与一个记忆方法
find 大概是 Linux 里最实用又最容易被低估的命令。它的核心语法只有一句:
bash复制find 起始路径 匹配条件 处理动作
起始路径是你要从哪个目录开始找;匹配条件包括文件名、类型、大小、时间;处理动作默认是打印结果,也可以用 -exec 或 -delete 做进一步操作。
匹配条件最常用的几个:
| 条件 | 含义 | 示例 |
|---|---|---|
| -name | 按文件名精确/通配符匹配 | find / -name "*.log" |
| -iname | 忽略大小写的文件名匹配 | find / -iname "README*" |
| -type | 按类型匹配 f/d/l | find /etc -type f |
| -size | 按大小匹配,+ 表示大于,- 表示小于 | find / -size +1G |
| -mtime | 按修改时间匹配(天),+7 表示超过 7 天 | find /var/log -mtime +7 |
| -mmin | 按修改时间匹配(分钟) | find /etc -mmin -5 |
| -user | 按属主匹配 | find /home -user zhangsan |
| -perm | 按权限匹配 | find / -perm -4000 |
我推荐一个记忆方法:find 就是把“在哪个范围、找什么特征、拿到后做什么”三件事写清楚。写命令前先在脑子里回答这三个问题,基本不会错。
典型组合使用:
bash复制# 找出 /var/log 下 30 天前的日志文件并删除
find /var/log -type f -name "*.log" -mtime +30 -delete
# 找出 / 下所有大于 500M 的文件
find / -type f -size +500M
# 找出系统里所有带 SUID 权限的文件(安全检查常用)
find / -type f -perm -4000
第三个命令是我在排查服务器安全问题时的例行检查项。SUID 文件过多或者出现不认识的 SUID 文件,通常意味着有风险。
3.2 文件类型判断的坑:-type f 和 [ -d ] 的区别
前面提到的 [ -d ] 是 shell 的内置 test 判断,它在脚本里用来判断某个路径是不是目录,属于条件分支的一部分:
bash复制if [ -d "/var/www/html" ]; then
echo "目录存在"
els
echo "目录不存在,开始创建"
mkdir -p /var/www/html
fi
而 -type d 是 find 的匹配条件,是在文件树上筛选目录。两者使用场景完全不同,新手容易搞混。记住一句话:[ -d ] 用于脚本里的“判断”,-type d 用于命令里的“筛选”。
3.3 删除文件/文件夹的安全姿势:rm -rf 的边界
热搜词里“linux删除文件夹命令”一直居高不下,说明这是新手最敢碰也最容易出事的地方。先说正解:
- 删除空目录:
rmdir dirname; - 删除非空目录及内容:
rm -r dirname; - 忽略确认直接删:
rm -rf dirname; - 强制删除文件:
rm -f filename。
-f 是 force,-r 是 recursive。组合起来 rm -rf 的杀伤力大家都听过,这里我不讲网上那些事故段子,就说两个实际建议。
第一,凡是含有变量、通配符、路径拼接的删除命令,执行前先 echo 打印一遍完整路径。比如你想删 /tmp/oldlogs/ 下所有文件,先跑 find /tmp/oldlogs -type f 看看列出的文件是不是预期内的,再动手。第二,尽量不要写 rm -rf /xxx/* 这种带通配符的清理命令,尤其是路径里有空格或特殊符号时,通配符展开后的内容可能完全不是你想的那样。
另外提一个替代方案:用 find ... -delete 代替 rm -rf,因为 find 的条件更精确,误删范围远小于 rm 加通配符。
3.4 grep、管道与其他文本小工具的配合
Linux 的哲学是“一个工具只做一件事,然后用管道把工具串起来”。这一节教你三个最常用的文本处理组合。
统计日志中的错误数量是每个运维都会干的事:
bash复制grep -c "ERROR" /var/log/app.log
查看日志中错误类型分布排行:
bash复制grep "ERROR" /var/log/app.log | awk '{print $5}' | sort | uniq -c | sort -rn
这条链路的思路是:先过滤出错误行,然后用 awk 取第五列(错误码),sort 排序让相同内容相邻,uniq -c 统计每个错误码出现次数,最后 sort -rn 按次数倒序排。以后遇到“系统出现了哪些错误、哪个最多”这种问题,一行命令搞定。
递归搜索文件内容也常用:
bash复制grep -r "listen 9090" /etc/nginx/
-r 递归,-n 显示行号。排查配置问题、搜索日志关键字时非常好用。
3.5 真实清理场景:找大文件、清旧日志
实际维护一台服务器,最常见的诉求就是“磁盘满了,删点东西”。标准排查流程如下:
- 先看磁盘整体使用:
df -h,确认哪个分区快满了; - 到对应分区找大文件:
find / -xdev -type f -size +1G 2>/dev/null,-xdev限制不跨文件系统,避免扫到 /proc、/sys 这些虚拟目录; - 看某个目录占用大小:
du -sh /var/log/* | sort -rh | head -20; - 确认日志增长趋势:
ls -lh /var/log/*.log,结合 mtime 判断哪些日志还在持续写入; - 清理策略:日志用 logrotate 定期轮转,临时文件用
find /tmp -type f -mtime +7 -delete定期清理。
我建议清理动作尽量写成一个脚本挂在 crontab 里,而不是每次手动执行。磁盘满是个慢性病,手动清理治标不治本。
4. 进程与服务:确认系统“跑得好不好”的正确方式
4.1 进程的直观理解:ps 和 top 怎么配合
进程管理是系统管理的核心科目,因为服务能不能对外提供能力,本质上就是进程在不在、活得好不好。
ps -ef 和 ps aux 是查看进程快照的两大主力。ps -ef 输出更标准,PID 是进程号,PPID 是父进程号,通过 PPID 能理清进程之间的父子关系;ps aux 则多了 CPU 占用、内存占用、VSZ/RSS 这些资源字段。日常看资源占用,用 ps aux --sort=-%mem | head -10 就能列出内存占用前 10 的进程。
top 是动态刷新版的 ps,按 CPU 排序。进入 top 后按 M 按内存排序,按 P 按 CPU 排序,按 1 查看每个核心的负载。如果你想在脚本里用,就用 top -bn1 以批处理模式输出一次快照。
要单独查某个进程可不可以 ps -ef | grep nginx,但这个命令有个坑:它会把自己也列出来,因为 grep 本身也是一个进程。用 pgrep -a nginx 更干净。
4.2 端口排查:9090 端口被占用的标准流程
热搜词里“linux的9090端口什么再用”是个典型的端口排查问题。当你要部署一个服务,结果发现端口被占,标准排查流程是这样的:
bash复制# 查看某个端口被谁监听
ss -tlnp | grep 9090
ss 是现在推荐的套接字查看工具,-t 只看 TCP,-l 只看监听状态,-n 不解析域名,-p 显示进程信息。老命令 netstat 功能类似,但很多新系统默认不装了。
如果输出是:
bash复制LISTEN 0 128 0.0.0.0:9090 0.0.0.0:* users:(("java",pid=12345,fd=27))
你就知道是 PID 12345 的 java 进程占用了 9090。再进一步看这个进程的详细信息:
bash复制ps -p 12345 -f
ls -l /proc/12345/cwd # 看进程的工作目录
ls -l /proc/12345/exe # 看进程的可执行文件路径
/proc 目录是一个虚拟文件系统,每个进程都有一个对应的数字目录。当你不确定一个陌生进程是什么来头时,/proc/PID/exe 和 /proc/PID/cwd 是最直接的线索。
4.3 systemctl 管理服务:start/stop/enable/status
现代 Linux 发行版的服务管理统一由 systemd 负责,systemctl 是与它交互的命令行工具。一套完整的服务管理操作包括:
bash复制systemctl start nginx # 启动服务
systemctl stop nginx # 停止服务
systemctl restart nginx # 重启服务(改了配置后用)
systemctl reload nginx # 平滑重载配置,不中断服务
systemctl status nginx # 查看服务状态和最近日志
systemctl enable nginx # 设置开机自启
systemctl disable nginx # 取消开机自启
systemctl --failed # 查看所有启动失败的服务
status 输出里最值得看的是 Active 行。active (running) 是正常,active (exited) 表示进程跑完退出了(常见于一次性任务),failed 表示启动失败,需要立刻处理。
服务的管理单元放在 /etc/systemd/system/ 和 /lib/systemd/system/ 目录下,以 .service 后缀结尾。如果你写了一个自己的服务脚本,可以自己写一个 unit 文件来托管。基本模板:
ini复制[Unit]
Description=My Custom Service
[Service]
ExecStart=/usr/local/bin/myserver
Restart=always
User=zhangsan
[Install]
WantedBy=multi-user.target
写完放到 /etc/systemd/system/myserver.service,然后 systemctl daemon-reload 让 systemd 重新加载。这个能力很重要,因为生产环境里你很少直接用 nohup ./xxx & 跑服务,而是用 systemd 托管,这样能自动重启、能看日志、能开机自启。
4.4 进程不响应/僵死时的处理思路
线上服务卡死是每个运维都绕不开的经历。我遇到的典型情况是:接口不响应,进程还活着,CPU 占用 100%。
处理思路是分层的:
- 看整体负载:
top,确认是不是某个进程占用全部 CPU; - 定位 Java/Python 应用内部:如果是 Java,用
jstack PID看线程栈;Python 用 py-spy; - 确认不是资源问题后,果断重启服务:
systemctl restart xxx,但重启前记得先保留现场(进程快照、日志)。
如果进程变成僵尸状态(Z),说明它的父进程没有正确回收子进程退出状态。僵尸进程本身不占 CPU,但数量多了会占满 PID 表,导致新进程无法创建。处理方法不是 kill 僵尸进程(kill 不掉,它已经死了),而是 kill 它的父进程,让 init 回收。找到父进程:ps -o ppid= -p 僵尸PID。
kill 命令的强度:kill PID 是发送 SIGTERM(15),让进程自己收尾退出;kill -9 PID 是 SIGKILL,强制内核杀掉进程。优先用 SIGTERM,因为很多程序需要处理未完成的事务,SIGKILL 可能造成数据损坏。只有 SIGTERM 无效时才考虑 -9。
4.5 面试常问:如何快速定位负载高的原因
最后这部分既是运维基本功,也是 Linux 面试高频题。当 top 显示 load average 很高时,标准排查链路是:
bash复制uptime # 看 1/5/15 分钟负载
top -bn1 # 看 CPU 占用前几名进程
iostat -x 1 # 看磁盘 I/O 是否饱和
free -h # 看内存是否吃紧
ss -s # 看连接数是否异常
dmesg -T | tail # 看内核是否有 OOM 或硬件报错
load average 高不代表 CPU 忙,也可能是磁盘 I/O 在等、内存不够在换页、或者 D 状态进程卡在 IO 上。我见过最坑的一次,负载高是因为某进程疯狂写日志把磁盘写满了,CPU 时间全耗在 IO 等待上。所以排查绝对不要只看 CPU,要 CPU、内存、磁盘、IO 一起看。
5. 软件安装:apt、nginx 与 Docker 背后的统一逻辑
5.1 包管理器的核心逻辑:仓库、索引、依赖
Linux 装软件跟 Windows 最大的区别是:Windows 下载安装包、双击下一步;Linux 绝大多数情况是敲一条命令,包管理器自动帮你从仓库下载、解决依赖、完成安装。
不同发行族各有对应:
| 发行版 | 包管理工具 | 仓库配置目录 | 在线安装命令 |
|---|---|---|---|
| Debian/Ubuntu | apt | /etc/apt/sources.list.d/ | apt install |
| CentOS/RHEL | dnf/yum | /etc/yum.repos.d/ | yum install |
| Arch | pacman | /etc/pacman.conf | pacman -S |
| 国产的 openEuler/UOS | dnf 或 yum | /etc/yum.repos.d/ | dnf install |
apt update 做的事是从仓库拉取软件索引,apt install nginx 才是真正安装。如果你从来没 update 过就直接 install,要么提示找不到包,要么装的是旧版本。所以新服务器到手第一步永远是 update。
依赖问题在 Linux 上自动帮你解决,这是包管理器最大的价值。你装 nginx 时,它会把 libpcre、zlib、openssl 这些依赖一起装好;如果某个依赖版本冲突,它还会提示。这也是为什么我建议能用包管理器就别自己编译,编译安装的依赖管理和卸载都非常麻烦。
5.2 用 nginx 走一遍“装、启、配、验”的完整链路
以 Ubuntu 上安装 nginx 为例,一条完整链路:
bash复制sudo apt update
sudo apt install -y nginx
systemctl status nginx
sudo systemctl enable --now nginx
curl -I http://127.0.0.1
enable --now 是 enable 和 start 的合并写法,设置开机自启并立即启动。curl -I 是只拿响应头,看到 HTTP/1.1 200 OK 就说明 nginx 跑起来了。
nginx 的默认站点配置在 /etc/nginx/sites-available/default,实际生效的是 /etc/nginx/sites-enabled/ 下的软链接。这种 available/enabled 两个目录的设计是为了方便多站点管理:想启用一个站点就建软链接,想停用就删软链接,不需要动原配置文件。
修改完配置记得先测试再重载:
bash复制sudo nginx -t
sudo systemctl reload nginx
nginx -t 会检查所有配置文件的语法,通过后才 reload。千万别改完配置直接 restart,一旦语法错误就会导致 nginx 启动失败,线上服务直接中断。reload 则是平滑重载,不中断服务,这个习惯是衡量是否专业的分水岭。
5.3 Docker 真的是另一套逻辑吗:镜像与容器
现在很多服务器上装软件已经不用传统包管理器了,而是用 Docker 容器。很多初学者觉得 Docker 是另一个维度的东西,其实它的核心逻辑跟包管理器异曲同工。包管理器的“仓库”对应 Docker 的“镜像仓库”,包管理器的“安装包”对应 Docker 的“镜像”,包管理器的“已安装软件”对应 Docker 的“容器”。
安装 Docker 本身(Ubuntu 快速版):
bash复制sudo apt update
sudo apt install -y docker.io
sudo systemctl enable --now docker
docker --version
拉取并运行一个 nginx 容器:
bash复制docker run -d --name web -p 80:80 nginx:latest
docker ps
-d 后台运行,--name web 给容器起名,-p 80:80 把宿主机的 80 端口映射到容器的 80 端口。这条命令执行后,宿主机 80 端口访问的就是容器里的 nginx。
日常运维常用的几个命令:
bash复制docker ps -a # 查看所有容器(含已停止)
docker logs web # 查看容器日志
docker exec -it web bash # 进入容器内部
docker stop web && docker rm web # 停止并删除容器
docker images # 查看本地镜像
docker image prune # 清理悬空镜像
用 Docker 部署的最大优势是环境一致性:镜像里装好了所有依赖和配置,推到哪台机器上都能跑出一模一样的环境。这也是为什么现在很多开源项目都提供 Docker 方式安装,比自己编译省心太多。
5.4 镜像加速与国内镜像源配置
很多国内用户用 Docker 时感觉拉镜像特别慢,这是正常现象——默认的 Docker Hub 仓库远在海外。解决方案是配置镜像加速或者国内镜像源。
编辑 /etc/docker/daemon.json:
json复制{
"registry-mirrors": [
"https://docker.m.daocloud.io"
]
}
然后重启 Docker:
bash复制sudo systemctl restart docker
需要注意的是,这类第三方加速地址时效性不稳定,建议在配置前先验证一下可用性。如果拉取镜像仍然很慢,另一个思路是换镜像仓库,很多国产云容器镜像服务(如阿里云容器镜像服务 ACR)提供了扶助的官方镜像同步,速度更快。
对于 apt 源同理,国内云服务器默认用的可能是官方源,速度感人。把源换成阿里云或清华源,apt update 的速度会有质的提升。修改源文件在 /etc/apt/sources.list,或者放在 /etc/apt/sources.list.d/ 下。我通常备份原文件后,直接用 sed 替换镜像地址。
5.5 安装软件时的常见问题自检清单
最后给一个安装软件时的自检清单,按优先级排列:
- 装不上提示找不到包?先
apt update或者dnf makecache,刷新索引; - 提示依赖冲突?看是哪个包冲突,优先考虑从官方仓库装,别乱加第三方源;
- 装好后命令找不到?可能命令不在 PATH 里,
which xxx查一下,或者软件的可执行文件放在/usr/sbin/下需要用sudo路径执行; - 服务起不来?先
systemctl status 服务名看具体报错,再journalctl -u 服务名 -n 50看最近 50 行日志; - Docker 拉镜像失败?确认网络和 daemon.json 配置,
docker info查看当前镜像源是否生效。
这个清单我基本每次部署新服务都会走一遍,踩的坑多了,效率反而高。记住一个原则:报错日志才是最好的老师,别靠猜。
第三章的核心内容到这里就铺完了。你可能会发现,这些内容单拎出来每一个命令都不复杂,真正难的是把它们串联起来解决实际问题的思路。我的体会是,用户管理和权限理解是 Linux 的基石,文件查找和文本处理是效率工具,进程与服务是运维手感,软件安装是让系统真正产生价值的入口。把这四块打通,你再去接触 Shell 脚本、网络配置、系统调优,都会有如鱼得水的感觉。
