Linux 命令行的学习曲线,往往不是卡在命令数量上,而是卡在没有建立“命令在操作系统里到底动了什么”的心智模型。很多人背了几十个命令,真正登录服务器后仍然不知道先敲哪一条:磁盘满了找不到大文件,服务起不来只会重启,权限报错就一路 chmod 777,日志刷屏却定位不到关键行。云计算岗位日常面对的恰恰是这些场景,命令行不是加分项,而是最基本的操作界面。下面这条主线从命令行的管理对象讲起,先准备一台可以反复折腾的环境,再把文件、权限、进程、文本处理、软件安装和网络排查依次跑通,每一步都给出可复制的命令、预期输出和出错后的排查顺序。读者跟着做完,应该能独立完成一台 Linux 服务器的日常巡检、故障定位和基础运维操作,而不是停留在“看得懂但写不出”的状态。
1. Linux 命令行的四类管理对象:先建立心智模型再背命令
命令行让人不适应的地方在于,它把图形界面里“看得见的东西”全部抽象成了文字。桌面环境里删除文件是拖进回收站,命令行里删除文件是告诉内核“把这个目录项从父目录里摘掉”。动作没变,只是表达方式变了。理解这一层,命令就不再是需要死记的字符串,而是对某类对象的操作请求。
1.1 从图形界面到命令行,改变的只是表达方式
图形界面把操作对象可视化:图标代表文件,任务管理器代表进程,用户设置代表账号。命令行把同一批对象变成了路径、PID、UID 这些标识符。所以学命令的第一件事,是知道每条命令作用于哪一类对象,而不是记住它的拼写。
举个对比。图形界面里查看磁盘占用,需要打开磁盘分析工具,等它扫描完再点开目录树。命令行里对应两条命令:df -h 看文件系统层面的整体使用率,du -sh /var/* 看具体目录占了多少空间。前者回答“哪个分区满了”,后者回答“哪个目录把分区撑满了”。两条命令解决的是同一个问题的两个层次,搞清楚这个层次关系,比记住参数更重要。
再比如“服务起不来”。图形界面里可能只有一个红色状态点。命令行里则是一条完整的证据链:systemctl status 看服务状态和退出码,journalctl -u 看服务自己的日志,ss -lntp 看端口有没有被别的进程占用,df -h 和 free -h 看是不是资源耗尽。命令行的优势不在于快,而在于每一步都能拿到可验证的证据。
注意:不要试图一次性记住所有命令。先按“文件、进程、用户、网络”四类对象分组,每组掌握五到八个高频命令,剩下的用到时再查手册,效率反而更高。
1.2 文件、进程、用户、网络:所有命令都落在这四类对象上
Linux 有一句流传很广的话叫“一切皆文件”,这句话在排查问题时特别有用。普通文件、目录、磁盘设备、网络套接字、内核参数,在文件系统里都有对应的路径。/proc/cpuinfo 是 CPU 信息,/proc/meminfo 是内存信息,/dev/sda 是块设备。理解了这层映射,很多“神秘”的命令就有了统一的解释。
| 管理对象 | 典型命令 | 解决的问题 | 常用证据来源 |
|---|---|---|---|
| 文件与目录 | ls、cp、mv、find、du |
定位、查看、清理、批量处理 | 路径、大小、修改时间 |
| 进程与服务 | ps、top、kill、systemctl |
谁在运行、谁在占资源、怎么停 | PID、CPU/内存占比、退出码 |
| 用户与权限 | id、chmod、chown、sudo |
谁能访问、为什么被拒绝 | UID/GID、权限位、umask |
| 网络与端口 | ip、ss、curl、ping |
通不通、谁在监听、返回什么 | 监听地址、连接状态、状态码 |
这四类对象之间还会互相牵连。一个“网站打不开”的问题,可能是文件权限不对(403)、进程没启动(502)、端口被占用(启动失败)、或者安全组没放行(超时)。排查的本质,就是按这四类对象逐个排除。
1.3 一条命令的解剖:命令、选项、参数与退出码
一条完整的命令由四部分组成:命令名、选项、参数、退出码。以 ls -lh /var/log 为例,ls 是命令名,-lh 是选项(-l 长格式,-h 人类可读的大小),/var/log 是参数,退出码在执行后用 echo $? 查看。
退出码是很多人忽略的部分,但它在脚本和自动化里极其关键。Linux 约定 0 表示成功,非 0 表示失败,不同数值代表不同错误类型。grep 找不到匹配时返回 1,命令本身出错返回 2。写 shell 脚本时如果只用 if grep ... 判断,就要清楚 1 和 2 的语义差别。
bash复制ls -lh /var/log
echo $?
grep -q "ERROR" /var/log/app.log
echo $?
选项有三种常见写法:短选项 -l、短选项合并 -lh、长选项 --human-readable。短选项能合并的前提是不需要额外值,像 -n 10 这种带值的就不能随便合并。参数则分为位置参数和可变参数,cp 的最后一个参数永远是目标位置,前面都是源。
1.4 遇到不认识的命令,先用这三条路查
实际工作中不可能记住所有命令。查文档的能力比记忆更重要,而且顺序有讲究。
第一条路是 --help,速度最快,给出常用选项的简要说明。第二条路是 man,给出完整手册,包括参数、退出码、相关文件和环境变量,按 / 可以搜索关键字,按 q 退出。第三条路是 apropos,当你只知道要做什么、不知道命令叫什么时用它按关键词搜索手册摘要。
bash复制ls --help
man 5 crontab
apropos "disk usage"
man 后面的数字表示手册分区,1 是用户命令,5 是文件格式,8 是系统管理命令。查 crontab 的格式要看 man 5 crontab,查命令用法要看 man 1 crontab,这是新手最容易混淆的一点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 准备一台可以随便折腾的 Linux:学习环境与首次登录检查
命令行的学习必须动手,光看不动手,遇到报错就无从下手。学习环境的核心要求不是配置多高,而是“能快照、能重装、敢删文件”。生产服务器上不敢执行的命令,在学习环境里要反复练到形成条件反射。
2.1 四种常见学习环境对比
不同环境的差异主要在隔离性、启动速度和网络可达性上。选择哪一种,取决于你当前的学习目标。
| 环境类型 | 典型方案 | 优点 | 局限 | 适合场景 |
|---|---|---|---|---|
| 本地虚拟机 | VirtualBox、VMware | 完全隔离,可打快照,可断网练习 | 占资源,启动慢 | 系统安装、分区、内核参数练习 |
| 云服务器 | 各云厂商的入门配置实例 | 自带公网地址,接近真实运维 | 有费用,误操作影响真实环境 | SSH、防火墙、服务部署练习 |
| 容器 | Docker、Podman | 秒级启动,资源占用小 | 默认无 systemd,不适合练服务管理 | 命令练习、文本处理、脚本调试 |
| 桌面子系统 | WSL2 等 | 与本机文件互通,启动快 | 与真实服务器仍有差异 | 日常命令熟悉、开发辅助 |
如果目标是云计算方向,建议组合使用:本地虚拟机练系统安装和分区,云服务器练 SSH 和服务部署,容器练命令和脚本。三者的差异本身也是知识点,比如容器里 systemctl 通常不可用,这不是命令错了,而是容器默认不跑 init 进程。
2.2 首次登录后的检查清单
拿到一台新机器,不要急着装软件。先花两分钟确认系统身份和资源状态,这几条命令能避免后面很多莫名其妙的问题。
bash复制cat /etc/os-release
uname -r
whoami
id
df -h
free -h
ip addr
/etc/os-release 给出发行版和版本号,决定了后面用 apt 还是 dnf。uname -r 是内核版本,装驱动或编译模块时要对得上。id 输出当前用户的 UID、GID 和所属组,判断有没有 sudo 权限靠它。df -h 和 free -h 是资源基线,后面出现“磁盘满”“内存不足”时有个对照。
ip addr 替代了老教程里的 ifconfig。很多新系统默认不装 net-tools,ifconfig 会提示 command not found,这不是系统坏了,而是工具被更现代的 iproute2 取代了。
2.3 目录结构与路径:相对路径和绝对路径的区别
FHS 标准规定了 Linux 目录的用途,记住主要几个就够日常使用。
| 目录 | 用途 | 日常会碰到的场景 |
|---|---|---|
/etc |
配置文件 | 改 nginx、ssh、服务的配置 |
/var |
可变数据 | 日志在 /var/log,网站数据在 /var/www |
/usr |
系统程序与库 | 可执行文件在 /usr/bin、/usr/sbin |
/home |
普通用户家目录 | 用户自己的脚本和配置 |
/tmp |
临时文件 | 权限宽松,可能被系统清理 |
/opt |
第三方软件 | 手动安装的软件常放这里 |
/proc |
内核与进程信息 | 排查时读 CPU、内存、进程状态 |
路径分绝对路径和相对路径。以 / 开头的是绝对路径,从根目录算起;不以 / 开头的是相对路径,从当前工作目录算起。cd /var/log 和 cd log 在 /var 下效果相同,但在别的位置就完全不同。脚本里一律推荐用绝对路径,避免因为执行位置不同导致找不到文件。
还有四个特殊路径符号要记住:. 是当前目录,.. 是上级目录,~ 是当前用户家目录,- 是上一次所在目录。cd - 在两个目录之间来回切换时非常实用。
2.4 SSH 登录与基础安全设置
云服务器基本都通过 SSH 登录。最常见的连接方式是密钥认证,比密码更安全,也便于自动化。
bash复制ssh-keygen -t ed25519 -C "dev@example.com"
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@192.0.2.10
ssh user@192.0.2.10
生成密钥时建议用 ed25519,比 RSA 更短更快,兼容性在现代系统上没有问题。如果必须用 RSA,长度至少 3072 位。ssh-copy-id 会把公钥追加到目标机器的 ~/.ssh/authorized_keys,并自动处理目录权限。
服务端的加固集中在 /etc/ssh/sshd_config。修改前先备份,改完用 sshd -t 校验语法,再重启服务,避免把自己锁在门外。
bash复制sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo sshd -t
sudo systemctl restart sshd
常见的安全项包括禁用 root 直接登录、禁用密码认证、限制可登录用户。这里要注意顺序:先确认普通用户能用密钥登录成功,再关闭密码认证。反过来的话,一旦密钥有问题就彻底进不去了。
注意:修改 SSH 配置时,保持一个已登录的会话不要断开,另开一个窗口测试新配置。测试通过后再关闭旧会话,这是最稳妥的验证方式。
3. 文件与目录:把查找、查看、修改、清理练成固定动作
文件操作是命令行使用频率最高的一类,也是最容易出事故的一类。rm -rf 的破坏力不需要多解释,关键是养成几个固定习惯:删除前先 ls 确认,批量操作先用 echo 打印目标,路径变量用严格的空值检查。
3.1 定位与浏览:pwd、cd、ls
三个最基础的命令决定了你在文件系统里的位置感。pwd 打印当前绝对路径,cd 切换目录,ls 列出内容。
bash复制pwd
cd /var/log
ls -alh
ls -lt | head -n 10
ls -alh 的组合含义是:-a 显示隐藏文件(以 . 开头的文件),-l 长格式输出,-h 把大小转成 K/M/G。长格式输出的第一列是权限位,后面依次是硬链接数、所有者、所属组、大小、修改时间、文件名。
ls -lt 按修改时间倒序排列,配合 head 就能快速找到最近被改动的文件。排查“配置文件被谁改了”这类问题时,这条命令比翻日志快得多。
3.2 创建、复制、移动、删除的安全习惯
创建目录用 mkdir,-p 可以递归创建多级目录,且目录已存在时不报错,写脚本时几乎总是要加。创建空文件用 touch,它同时能更新已有文件的时间戳。
bash复制mkdir -p /data/app/logs
touch /data/app/logs/app.log
cp -a /etc/nginx /backup/nginx-$(date +%F)
mv app.log app.log.20260101
ln -s /data/app/current /data/app/releases/v1
cp -a 相当于 -dR --preserve=all,会保留权限、时间戳和软链接本身。备份配置文件时不用 -a,恢复后权限可能不对,服务照样起不来。
mv 在同一文件系统内是重命名,跨文件系统时实际是复制加删除,大文件会有明显耗时。ln -s 创建软链接,第一个参数是目标,第二个是链接名,顺序搞反是新手常见错误。
删除是最需要克制的操作。rm -rf 不进入回收站,删掉就没了。批量删除前先用 ls 或 find 打印一遍目标列表。
bash复制find /data/tmp -name "*.tmp" -mtime +7 -print
find /data/tmp -name "*.tmp" -mtime +7 -delete
先 -print 确认范围,再改成 -delete,这个两步走习惯能避免绝大多数误删。
3.3 查看文件内容的四种方式与适用场景
查看文件不是只有 cat。文件大小和用途不同,工具选择也不同。
| 命令 | 适用场景 | 注意事项 |
|---|---|---|
cat |
小文件整体查看 | 大文件会刷屏,慎用 |
less |
大文件分页浏览 | 支持 / 搜索,q 退出 |
head -n 50 |
看文件开头 | 适合看配置头部、CSV 表头 |
tail -n 100 |
看文件结尾 | 日志排查最常用 |
tail -f |
实时跟踪新增内容 | 文件被轮转后会失效,用 -F |
tail -f 和 tail -F 的区别值得单独说。-f 跟踪的是文件描述符,日志轮转后原文件被重命名,新文件写入的内容就看不到了。-F 会检测文件名,轮转后自动重新打开,生产环境看日志建议用 -F。
bash复制tail -F /var/log/nginx/error.log
less +F /var/log/messages
less +F 是另一个实用技巧,它像 tail -f 一样实时刷新,但按 Ctrl+C 可以切回普通浏览模式,往回翻看历史内容,比单纯 tail -f 更灵活。
3.4 查找文件与查找内容:find 与 grep
find 按文件属性查找,grep 按文件内容查找,两者解决的是不同维度的问题。混淆这两个命令,是新手搜索效率低的主要原因。
bash复制find /var/log -type f -name "*.log" -size +100M
find /etc -type f -mtime -1
find /data -type d -name "cache" -prune -o -type f -name "*.php" -print
grep -rn "ERROR" /var/log/app --include="*.log"
grep -c "GET /api" /var/log/nginx/access.log
find 的常用条件包括 -type(f 文件、d 目录)、-name(文件名,支持通配符)、-size(大小)、-mtime(修改时间,单位天)、-mmin(单位分钟)。-size +100M 表示大于 100MB,-mtime -1 表示一天内修改过。
grep -r 递归搜索目录时要注意性能,在大目录上跑可能很慢。加 --include 限定文件类型能显著提速。-n 显示行号,-i 忽略大小写,-v 反向匹配,-E 使用扩展正则,这几个是最常用的组合。
3.5 文件操作命令速查表
| 需求 | 命令 | 关键参数说明 |
|---|---|---|
| 看当前路径 | pwd |
无 |
| 切换目录 | cd |
- 回上次目录,~ 回家目录 |
| 列目录 | ls |
-a 隐藏文件,-l 长格式,-h 易读大小,-t 按时间 |
| 建目录 | mkdir |
-p 递归且已存在不报错 |
| 复制 | cp |
-a 归档模式,-r 递归 |
| 移动/重命名 | mv |
跨文件系统为复制加删除 |
| 删除 | rm |
-r 递归,-f 强制,慎用 |
| 建链接 | ln -s |
目标在前,链接名在后 |
| 看内容 | cat/less |
大文件用 less |
| 找文件 | find |
-type、-name、-size、-mtime |
| 找内容 | grep |
-r、-n、-i、-v、-E |
| 看磁盘 | df -h |
加 -i 看 inode |
4. 权限与用户:为什么生产环境不该直接用 root
权限报错是 Linux 新手遇到最多的问题,也是误操作最多的领域。看到 Permission denied 就 chmod 777,短期能跑通,长期会把系统的安全边界全部拆掉。理解权限位的含义,比记住一个万能数字更有价值。
4.1 rwx 权限位的含义与数字表示
Linux 文件权限分三组:所有者(user)、所属组(group)、其他人(other)。每组有读(r)、写(w)、执行(x)三个位,对应数字 4、2、1,加起来就是常见的八进制表示。
| 权限 | 字母 | 数字 | 对文件的意义 | 对目录的意义 |
|---|---|---|---|---|
| 读 | r | 4 | 查看内容 | 列出目录内文件名 |
| 写 | w | 2 | 修改内容 | 在目录内创建、删除文件 |
| 执行 | x | 1 | 作为程序运行 | 进入目录、访问其中文件 |
这里有一个容易误解的点:目录的写权限意味着能在里面删文件。一个文件本身是 444,如果所在目录对你有写权限,你依然可以删掉它。所以“文件只读”并不等于“删不掉”,删除动作由父目录权限决定。
常见权限组合有明确语义:644 是普通文件(所有者读写,其他人只读),755 是可执行文件和目录,600 是私密文件(如私钥),700 是私有目录。私钥文件权限必须是 600,否则 SSH 会拒绝使用。
4.2 chmod、chown 与 umask 的配合
chmod 改权限,chown 改所有者,umask 决定新建文件的默认权限。三者配合才能解释“为什么我新建的文件权限是这个值”。
bash复制chmod 644 /data/app/config.yml
chmod 755 /data/app/bin/start.sh
chmod -R 755 /data/app/static
chown app:app /data/app/config.yml
chown -R www-data:www-data /var/www/html
umask
umask 022
umask 是“权限掩码”,新建文件的权限等于基础权限减去掩码。文件基础权限是 666,目录是 777。umask 022 时,新文件是 644,新目录是 755。这也是绝大多数系统的默认值。
chmod -R 要特别注意,递归修改会把目录里的普通文件也加上执行位,变成不该有的 755。正确做法是分开处理。
bash复制find /data/app -type d -exec chmod 755 {} \;
find /data/app -type f -exec chmod 644 {} \;
按类型分别设置,才是安全的批量授权方式。
4.3 sudo 的正确用法与常见误用
sudo 让普通用户以其他身份执行命令,默认是 root。它的价值在于“按需提权”,而不是“人人都是 root”。
bash复制sudo systemctl restart nginx
sudo -u www-data ls /var/www/html
sudo -l
sudo -u 可以切换到指定用户执行,排查“网站目录为什么不可写”时很有用,因为你可以用 Web 服务自己的身份去验证权限。sudo -l 列出当前用户被允许执行的命令,进新环境先看一眼,能省很多试错。
配置 sudo 要用 visudo,它会做语法检查,避免写坏 /etc/sudoers 导致所有人无法提权。直接 vim /etc/sudoers 是高风险操作。
注意:生产环境不要给业务账号配置
NOPASSWD: ALL。真需要免密执行,就把命令限定到具体路径,比如只允许重启某个服务,而不是放开全部命令。
4.4 权限问题的排查顺序
遇到 Permission denied,按以下顺序检查,不要一上来就改权限。
- 用
id确认当前用户的 UID、GID 和所属组。 - 用
ls -l看目标文件的所有者、所属组和权限位。 - 用
namei -l /full/path/to/file逐级检查路径上每一层目录的权限。很多问题不是文件本身,而是中间某一层目录少了x。 - 用
getfacl检查是否有 ACL 规则覆盖了基础权限。 - 检查 SELinux 或 AppArmor 是否在拦截,用
getenforce看状态,用ausearch或dmesg找拒绝记录。 - 最后才考虑修改权限,并记录修改原因。
第 3 步是最容易被跳过的一步。用户看到文件是 644 就认为没问题,实际上父目录是 700 且属于别人,一样进不去。
5. 进程、服务与系统状态:服务起不来时按这条链路查
服务启动失败是最常见的生产问题。新手的第一反应是重启,重启不行就重装。有经验的运维会先收集证据:进程在不在、端口占没占、日志说了什么、资源够不够。这四步能覆盖大部分场景。
5.1 ps 与 top:看清谁在吃 CPU 和内存
ps 是静态快照,top 是动态刷新。排查瞬间故障用 ps,观察趋势用 top。
bash复制ps -ef | grep nginx
ps aux --sort=-%mem | head -n 10
top -b -n 1 | head -n 20
ps -ef 用标准格式列出所有进程,包含 PPID(父进程 ID),排查“谁启动了它”时很有用。ps aux 用 BSD 格式,--sort=-%mem 按内存倒序,配合 head 能立刻找到内存大户。
top 交互模式里几个快捷键值得记住:P 按 CPU 排序,M 按内存排序,1 展开每个 CPU 核心,q 退出。生产环境经常遇到 CPU 打满,先看是哪个进程,再看是用户态还是内核态占用高,方向完全不同。
5.2 kill 的信号语义与优雅退出
kill 不是“杀死”,而是“发送信号”。默认发送 SIGTERM(15),进程可以捕获它做清理工作,比如关闭连接、写完缓冲区、删除临时文件。SIGKILL(9)无法被捕获,进程直接被内核终止,可能留下脏数据。
bash复制kill -15 12345
kill -9 12345
kill -l
正确的停止顺序是先 -15,等几秒确认进程退出,再考虑 -9。直接 -9 在数据库、消息队列这类有状态服务上风险很高,可能造成数据不一致。
kill -l 列出所有信号。除了 15 和 9,SIGHUP(1)常用于让服务重读配置,SIGINT(2)对应 Ctrl+C,SIGSTOP(19)暂停进程。
5.3 systemctl 管理服务生命周期
现代发行版基本都用 systemd 管理服务。掌握这几个子命令,日常运维就够用了。
bash复制systemctl status nginx
systemctl start nginx
systemctl restart nginx
systemctl reload nginx
systemctl enable nginx
systemctl is-active nginx
systemctl list-units --type=service --state=running
restart 和 reload 的区别要分清。reload 让服务重读配置而不中断现有连接,前提是服务支持(nginx、sshd 都支持)。restart 是先停再起,会中断连接。生产环境能 reload 就不要 restart。
enable 是设置开机自启,和 start 是两件独立的事。一个服务可以正在运行但没设开机自启,重启机器后就没了。反过来,设了自启但当前没启动也很常见。
systemctl status 的输出里,重点看三处:Active 行看状态和退出码,Main PID 看主进程,最后几行日志看最近的错误。退出码 203 常见于权限问题,1 是通用失败,exited 后面跟的数字就是进程自己的返回值。
5.4 磁盘、内存、日志:三类最常用的现场证据
资源类问题有三个高频检查点:磁盘空间、inode 数量、内存和 swap。
bash复制df -h
df -i
du -sh /var/* | sort -rh | head -n 10
free -h
journalctl -u nginx --since "30 min ago" --no-pager
dmesg -T | tail -n 30
df -h 看空间,df -i 看 inode。这两者经常被混淆:磁盘还有空间但 inode 用尽,新建文件照样失败,报错是 No space left on device,但 df -h 显示还有剩余。大量小文件(缓存、会话文件、邮件队列)是 inode 耗尽的典型原因。
du -sh /var/* 按目录统计大小并排序,能快速定位是哪个目录在膨胀。注意 du 会遍历文件,在超大目录上执行会比较慢,可以先用 --max-depth=1 限制层级。
free -h 里 available 才是可用内存,free 列包含缓存,数值小是正常的。Linux 会把空闲内存用于文件缓存,真正需要时再释放,看到 free 很低就判断内存不足是常见误判。
journalctl -u 按服务过滤日志,--since 限定时间范围,--no-pager 避免进入分页模式。dmesg -T 看内核日志并显示可读时间,OOM Killer 杀进程、磁盘 I/O 错误、网卡异常都会在这里留痕。
5.5 服务启动失败的排查顺序
按下面的顺序走,基本不会漏。
systemctl status看状态和退出码,确认是启动失败还是启动后崩溃。journalctl -u 服务名 -n 100看服务日志里的第一条错误,不是最后一条。ss -lntp确认端口有没有被别的进程占用,报错通常是Address already in use。ls -l检查配置文件路径、权限和所有者,确认运行用户能读取。- 手动执行启动命令,把日志打到前台,能看到被 systemd 吞掉的输出。
df -h和free -h排除资源问题。dmesg -T | tail排除被 OOM Killer 杀掉的可能。
第 5 步很关键。systemd 会把标准输出重定向到 journal,但有些程序有自己的日志文件或者需要终端环境,手动跑一遍往往能直接看到原因。
6. 管道与文本处理:把重复劳动交给命令组合
Linux 命令行的真正威力不在单条命令,而在组合。每个命令只做一件小事,通过管道串起来完成复杂任务。这个设计思想在日志分析场景里体现得最明显。
6.1 重定向与管道:命令之间的数据流
每个进程默认有三个文件描述符:标准输入(0)、标准输出(1)、标准错误(2)。重定向改变它们的去向,管道把上一个命令的输出接到下一个命令的输入。
bash复制command > out.log
command >> out.log
command 2> err.log
command > all.log 2>&1
command 2>&1 | tee run.log
> 覆盖,>> 追加。这两个符号用错的后果不一样:>> 写成了 > 会清空原文件。清空日志文件是运维事故里很典型的一种,尤其在 echo "" > app.log 这类“清空日志”的操作中,路径写错就清错了文件。
2>&1 表示把标准错误重定向到标准输出当前指向的位置。顺序很重要:> all.log 2>&1 是两者都进文件,2>&1 > all.log 则是错误进终端、输出进文件,因为重定向是从左到右生效的。
tee 在把输出写入文件的同时保留屏幕显示,调试脚本时比单纯重定向方便。
6.2 grep、sed、awk 的分工
三个工具经常一起出现,但职责不同:grep 负责筛选行,sed 负责替换和按行编辑,awk 负责按列处理。
bash复制grep -E "ERROR|WARN" app.log
sed -n '100,120p' app.log
sed -i 's/old-domain.com/new-domain.com/g' /etc/nginx/conf.d/site.conf
awk '{print $1, $7}' access.log
awk -F: '$3 >= 1000 {print $1, $3}' /etc/passwd
sed -i 是原地修改,执行前一定先备份或者先不加 -i 跑一遍看输出。正则里的 / 如果出现在替换内容中,可以换分隔符,比如 sed -i 's#/old/path#/new/path#g',避免大量转义。
awk 默认按空白字符分列,$1 是第一列,$NF 是最后一列,$(NF-1) 是倒数第二列。-F 指定分隔符,处理 /etc/passwd 这类冒号分隔的文件时必须加。awk 还支持条件判断和求和,处理统计类需求比 grep 灵活得多。
bash复制awk '{sum += $10} END {print sum/1024/1024 " MB"}' access.log
6.3 sort、uniq、wc 做统计
统计类需求有一套固定套路:提取字段、排序、去重计数、再排序取前几名。
bash复制awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -n 10
awk '{print $9}' access.log | sort | uniq -c | sort -rn
wc -l access.log
uniq -c 只能对相邻的重复行计数,所以必须先 sort。这个顺序搞反,统计结果就是错的,而且错得很隐蔽,不会报错。sort -rn 是按数值倒序,-n 不能省,否则 10 会排在 9 前面。
wc -l 统计行数,-c 统计字节数,-w 统计词数。快速确认日志规模、文件行数时很实用。
6.4 实战:从访问日志里统计 Top IP 和状态码
假设有一份 nginx 默认格式的访问日志,字段依次是 IP、时间、请求、状态码、大小等。下面的命令能回答几个最常见的运维问题。
bash复制# 访问量前 10 的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -n 10
# 各状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 只看 5xx 错误对应的请求路径
awk '$9 ~ /^5/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# 统计总流量(假设第 10 列是字节数)
awk '{sum += $10} END {printf "%.2f MB\n", sum/1024/1024}' /var/log/nginx/access.log
这几条命令的价值在于可组合。想加时间过滤,前面接 grep "2026-01-01";想排除静态资源,中间加 grep -v -E "\.(css|js|png)$"。掌握这个套路,大部分日志分析需求不需要写脚本。
注意:日志格式不是固定的。自定义
log_format后字段位置会变,执行统计前先用head -n 3看一眼实际内容,确认字段位置再写awk。
7. 软件安装与网络连通性排查
装软件和查网络是两件看起来不相关的事,但在实际排查中经常连在一起:服务装好了却访问不了,问题可能在包没装全,也可能在端口没监听、防火墙没放行、DNS 解析不对。
7.1 包管理器差异与常用操作
不同发行版的包管理器不同,但操作语义基本对应。
| 操作 | Debian/Ubuntu(apt) | RHEL 系(dnf/yum) | Alpine(apk) |
|---|---|---|---|
| 更新索引 | apt update |
dnf makecache |
apk update |
| 安装 | apt install nginx |
dnf install nginx |
apk add nginx |
| 卸载 | apt remove nginx |
dnf remove nginx |
apk del nginx |
| 搜索 | apt search nginx |
dnf search nginx |
apk search nginx |
| 查看信息 | apt show nginx |
dnf info nginx |
apk info nginx |
| 列出已安装 | apt list --installed |
dnf list installed |
apk info |
| 清理缓存 | apt clean |
dnf clean all |
apk cache clean |
有两个坑要提前说。第一,apt update 是更新软件源索引,不是升级已安装的软件,升级要用 apt upgrade。第二,生产环境不要随手执行全量升级,内核和关键库的版本变化可能影响正在运行的服务,升级前要确认变更范围并有回滚方案。
装完软件后确认版本和安装位置,能避免“装了两个版本、跑的是旧的那个”这类问题。
bash复制which nginx
nginx -v
dpkg -L nginx | head
rpm -ql nginx | head
which 看当前 PATH 里解析到哪个可执行文件,dpkg -L 和 rpm -ql 列出包安装的所有文件路径,排查配置文件位置时很有用。
7.2 网络排查命令的分层使用
网络问题要分层查,从本机地址、路由、端口、连通性到应用层响应,逐层排除。跳层排查容易白费功夫。
bash复制ip addr
ip route
ss -lntp
ping -c 4 192.0.2.10
curl -v http://127.0.0.1:8080/health
ip addr 确认网卡有没有 IP,ip route 确认默认网关在不在。容器环境里这两条命令经常暴露出“网卡没起来”或“路由缺失”的问题。
ss -lntp 是替代 netstat 的现代工具,-l 只看监听,-n 不做域名解析(快),-t 只看 TCP,-p 显示进程(需要 root)。输出里的监听地址很关键:0.0.0.0:8080 表示所有网卡都可访问,127.0.0.1:8080 表示只有本机能访问。很多“外网访问不了”的问题,根因就是服务只监听了本地回环。
curl -v 能看到完整的请求和响应过程,包括 DNS 解析、TCP 连接、TLS 握手、HTTP 状态码。比起 ping,它更接近真实用户的访问路径。
ping 不通不代表服务不可用,很多云环境默认禁 ICMP。判断端口通不通,用 curl 或 nc -zv host port 更准确。
7.3 一个典型的“网站访问不了”排查流程
按下面的顺序走,能把问题范围快速缩小到某一层。
- 本机确认服务进程在不在:
systemctl status 服务名。 - 确认端口在监听:
ss -lntp | grep 端口,重点看监听地址。 - 本机自测:
curl -v http://127.0.0.1:端口/,排除应用层问题。 - 内网另一台机器测:
curl -v http://内网IP:端口/,排除监听地址问题。 - 检查本机防火墙:
firewall-cmd --list-all或iptables -L -n。 - 检查云平台安全组规则是否放行该端口。
- 检查 DNS 解析:
dig 域名 +short或nslookup 域名,确认解析到预期 IP。 - 检查反向代理配置和上游地址是否正确,看代理层日志里的上游错误。
第 3 步和第 4 步的对比特别有价值。本机能访问、内网不能访问,问题基本锁定在监听地址或防火墙;两边都不能访问,问题在应用本身。这个二分法能省掉大量猜测。
8. 常见坑、可复用清单与下一步练习
命令行的熟练度来自重复和纠错。下面这几个坑在实际项目里出现频率极高,提前知道能少走很多弯路。
8.1 六个高频错误与正确做法
| 错误现象 | 常见原因 | 检查方式 | 正确做法 |
|---|---|---|---|
| 脚本删除了错误目录 | 变量为空,rm -rf $DIR/ 变成 rm -rf / |
echo 打印变量值 |
脚本开头 set -u,用 ${DIR:?} 强制非空 |
| 日志被清空 | 想追加却用了 > |
查 shell history 和文件大小 | 追加用 >>,清空用 truncate -s 0 并确认路径 |
| 目录权限全变 755 | chmod -R 755 一刀切 |
find 目录 -type f -perm 755 |
按 -type d 和 -type f 分开设置 |
| 磁盘有空间但写入失败 | inode 耗尽 | df -i |
清理小文件,检查缓存和会话目录 |
| 服务重启后配置不生效 | 改了配置没 reload,或改错了环境 | nginx -t 校验,systemctl reload |
改完先校验语法再 reload,确认文件路径 |
| 外网访问不了但本机正常 | 服务只监听 127.0.0.1 |
ss -lntp 看监听地址 |
配置改为 0.0.0.0 或指定内网网卡地址 |
第一个坑值得展开。shell 脚本里 rm -rf $DIR/ 在 DIR 未定义时会展开成 rm -rf /,后果不用多说。防御写法有三种:脚本开头加 set -u,未定义变量直接报错退出;用 ${DIR:?DIR is required},变量为空时终止;写路径时留一个明确的层级,比如 rm -rf "${DIR}/tmp/",即使变量为空也只会删 /tmp/ 下的内容。三种可以叠加使用。
8.2 上线前与交付前的检查清单
下面这份清单适合在一台服务器交付或一次部署上线前过一遍。
- 系统信息确认:
cat /etc/os-release、uname -r与文档记录一致。 - 时间同步:
timedatectl确认时区和 NTP 同步状态,时间偏差会导致证书校验和日志排查失真。 - 磁盘余量:
df -h和df -i都在安全阈值以上。 - 内存与 swap:
free -h确认available充足,swap 策略符合预期。 - 账号权限:
id确认服务运行账号,sudo -l确认提权范围最小化。 - 关键目录权限:配置文件
644,私钥600,可执行脚本755,属主正确。 - 服务状态:
systemctl is-enabled和is-active都符合预期。 - 端口监听:
ss -lntp确认监听地址和预期一致,无多余端口暴露。 - 日志落盘:确认日志路径存在、有轮转策略、磁盘不会被写满。
- 防火墙与安全组:只放行必要端口,来源限制到具体网段。
- 备份与回滚:配置文件有备份,变更前记录原始版本。
- 监控接入:CPU、内存、磁盘、进程存活至少四项有采集。
这份清单不需要每次全做,但新机器交付和重大变更前应该完整过一遍。
8.3 从命令到自动化:下一步学什么
命令敲熟之后,下一步是把重复操作脚本化。顺序建议是:先写简单的 shell 脚本处理固定的巡检任务,再学 cron 做定时执行,然后接触配置管理和容器化。
shell 脚本的入门不需要学全语法,先掌握变量、条件判断、循环、函数和错误处理五件事。重点是错误处理:set -e 让命令失败即退出,set -u 让未定义变量报错,set -o pipefail 让管道中任一环节失败都能被捕获。这三行几乎是生产脚本的标配。
bash复制#!/usr/bin/env bash
set -euo pipefail
LOG_DIR="/var/log/app"
THRESHOLD=80
usage=$(df -h / | awk 'NR==2 {gsub("%","",$5); print $5}')
if [ "$usage" -ge "$THRESHOLD" ]; then
echo "disk usage ${usage}% exceeds ${THRESHOLD}%" >&2
exit 1
fi
定时任务用 cron,crontab -e 编辑当前用户的任务,格式是分、时、日、月、周加命令。新手最容易错的是环境变量:cron 执行时的 PATH 和登录 shell 不同,脚本里用到非标准路径的命令要写绝对路径,或者在脚本开头显式设置 PATH。
再往后是容器和服务编排。容器里的 Linux 和物理机有差异:默认没有 systemd,进程 PID 1 的语义不同,信号处理需要特别注意。带着这些差异去学,比直接照搬物理机经验要顺得多。
最后给一个练习建议:找一台空闲机器,从零部署一个静态站点加反向代理,全程只用命令行完成,包括装包、建目录、配权限、写配置、启动服务、开放端口、看日志、模拟一次故障并修复。这一套流程走通,日常运维的大部分场景都能应对。
