运维命令速查手册
覆盖 Linux / Windows / PowerShell / Git / Docker / Kubernetes / 数据库 / Nginx / 正则 / 网络设备(华为·华三·思科)/ SSH / 防火墙 / 磁盘证书 / systemd / 监控中间件的日常查阅与排障手册。
文档结构:命令速查表 → 场景解惑 Q&A → 生产实战案例 → 安全红线,共 18 章。急查问题先用下方速查索引直达章节。
最后更新:2026-07-27
目录
- 一、Linux 常用命令
- 二、Windows CMD 常用命令
- 三、PowerShell 常用命令
- 四、Linux 与 Windows 命令对照表
- 五、常见场景解惑
- 六、Git 常用命令
- 七、Docker 常用命令
- 八、Kubernetes 常用命令
- 九、数据库常用命令
- 十、Nginx 常用操作
- 十一、正则表达式速查
- 十二、网络设备常用命令
- 十三、网络设备堆叠配置
- 十四、SSH 与网络排障
- 十五、Linux 防火墙与性能分析
- 十六、磁盘 LVM 与 openssl 证书
- 十七、systemd、定时任务与监控中间件
- 十八、运维安全红线与通用注意事项
速查索引
遇到问题先看这里,直达对应章节。⚡ = 内含生产实战案例。
应急排障
| 遇到的问题 | 直达章节 |
|---|---|
| 磁盘满了 / 写不进文件(inode、句柄不释放) | 一⚡ / 五Q1 / 十五⚡ / 十六⚡ |
| 端口在监听但外部连不上 | 五Q2 / 十五⚡ |
| CPU 100% / 系统卡顿 | 五Q9 / 十五 |
| 服务起不来 / 反复重启 | 八⚡ / 十七 |
| 接口超时(网络还是应用的锅?) | 十四⚡(抓包定位) |
| HTTPS 证书报错 / 快过期 | 十六 / 十⚡ |
| 日志里定位错误 / 统计攻击 IP | 一 / 十一⚡ / 三⚡ |
| 网络不通、丢包、DNS 异常 | 十四 |
| 发布出错要回滚 | 八(rollout)/ 七 / 六(revert) |
| 数据库慢 / 缓存穿透 | 九⚡ |
| Nginx 报 502/504/413/403 | 十 |
| 楼层/区域断网、环路、光衰 | 十二⚡ |
| 堆叠分裂(脑裂) | 十三⚡ |
| 消息队列堆积 | 十七⚡ |
| 服务器半夜重启了 | 三⚡(Windows)/ 十五(dmesg) |
日常操作
| 要做的事 | 直达章节 |
|---|---|
| 免密登录 / 跳板机 / 内网穿透 | 十四 |
| 两台机器传文件 / 增量备份 | 五Q5 / 十四⚡(rsync) |
| 程序托管为系统服务(开机自启) | 十七⚡ |
| 定时备份 / 定时任务 | 十七 |
| 磁盘扩容(在线不停机) | 十六⚡ |
| 数据库备份与恢复 | 九 |
| 进入容器调试 | 七 / 八 |
| 批量操作多台机器 | 三⚡(Windows)/ 一⚡ |
| 网络设备配置/堆叠 | 十二 / 十三 |
| 高危操作前必看 | 十八(红线清单+Checklist) |
一、Linux 常用命令
1. 文件与目录操作
| 命令 | 说明 | 常用示例 |
|---|---|---|
ls | 列出目录内容 | ls -lah(详细+人类可读+含隐藏文件) |
cd | 切换目录 | cd /var/log、cd ..、cd ~(回家目录)、cd -(回上次目录) |
pwd | 显示当前路径 | pwd |
mkdir | 创建目录 | mkdir -p a/b/c(递归创建多级目录) |
cp | 复制 | cp -r dir1 dir2(复制目录)、cp -a(保留权限) |
mv | 移动/重命名 | mv old.txt new.txt、mv file /tmp/ |
rm | 删除 | rm -r dir(删目录)、rm -f(强制不提示) |
touch | 创建空文件/更新修改时间 | touch new.txt |
ln | 创建链接 | ln -s /path/to/target link_name(软链接) |
find | 查找文件 | find / -name "*.log"(按名查找)、find . -mtime +7(7天前修改的) |
tree | 树状显示目录 | tree -L 2(只显示2层) |
2. 文件内容查看与处理
| 命令 | 说明 | 常用示例 |
|---|---|---|
cat | 查看/合并文件 | cat file.txt、cat a b > c |
less | 分页查看(可上下翻) | less big.log,按 /关键字 搜索,q 退出 |
head | 看开头几行 | head -n 20 file.log |
tail | 看结尾几行 | tail -f app.log(实时跟踪日志,排查问题神器) |
grep | 文本搜索 | grep -rn "error" ./logs(递归+行号)、grep -i(忽略大小写) |
wc | 统计行数/字数 | wc -l file.txt(统计行数) |
sort | 排序 | sort -n(数字排序)、sort -u(去重) |
uniq | 去重(需先排序) | `sort file |
awk | 按列处理文本 | awk '{print $1}'(取第1列)、`ps aux |
sed | 文本替换/编辑 | sed -i 's/old/new/g' file(全局替换并写回) |
cut | 按分隔符取列 | cut -d: -f1 /etc/passwd |
diff | 比较文件差异 | diff file1 file2 |
vi/vim | 编辑器 | i 进入编辑,Esc 后 :wq 保存退出,:q! 强制退出 |
3. 权限与用户
| 命令 | 说明 | 常用示例 |
|---|---|---|
chmod | 修改权限 | chmod 755 script.sh、chmod +x run.sh(加执行权限) |
chown | 修改属主 | chown user:group file、chown -R(递归) |
sudo | 以管理员身份执行 | sudo systemctl restart nginx |
su | 切换用户 | su - root |
whoami | 当前用户 | whoami |
id | 用户/组信息 | id username |
passwd | 修改密码 | passwd username |
useradd/userdel | 增删用户 | useradd -m newuser(同时建家目录) |
权限数字含义:
r=4, w=2, x=1,如755= 属主 rwx(7)、组 r-x(5)、其他 r-x(5)
4. 进程管理
| 命令 | 说明 | 常用示例 |
|---|---|---|
ps | 查看进程快照 | `ps aux |
top / htop | 动态查看进程/资源 | top,按 P 按CPU排序、M 按内存排序 |
kill | 结束进程 | kill -9 PID(强制杀死)、kill PID(正常终止) |
killall / pkill | 按名字杀进程 | pkill -f java |
jobs / bg / fg | 后台任务管理 | command &(后台运行)、jobs 查看、fg %1 拉回前台 |
nohup | 退出终端后继续运行 | nohup ./server &,输出默认到 nohup.out |
5. 磁盘与内存
| 命令 | 说明 | 常用示例 |
|---|---|---|
df | 磁盘空间 | df -h(人类可读) |
du | 目录/文件占用 | du -sh *(当前目录各项大小)、`du -sh ./* |
free | 内存使用 | free -h |
mount / umount | 挂载/卸载 | mount /dev/sdb1 /mnt |
fdisk / lsblk | 查看磁盘分区 | lsblk(树状显示块设备) |
6. 网络相关
| 命令 | 说明 | 常用示例 |
|---|---|---|
ping | 测试连通性 | ping -c 4 baidu.com(Linux 默认不停,要加次数或 Ctrl+C) |
curl | 发起 HTTP 请求 | curl -I url(只看响应头)、curl -X POST -d '{}' url |
wget | 下载文件 | wget -O out.zip url |
netstat / ss | 端口占用 | ss -tlnp 或 netstat -tlnp(查看监听端口及进程) |
ifconfig / ip addr | 查看 IP | ip addr(新命令) |
scp | 远程拷贝 | scp file user@host:/path/ |
ssh | 远程登录 | ssh user@host -p 22 |
telnet / nc | 测试端口连通 | nc -zv host 80、telnet host 3306 |
traceroute / mtr | 路由追踪 | traceroute baidu.com |
7. 压缩与解压
| 命令 | 说明 | 常用示例 |
|---|---|---|
tar | 打包/解包 | 压缩:tar -zcvf a.tar.gz dir/;解压:tar -zxvf a.tar.gz;只看内容:tar -tvf a.tar.gz |
zip / unzip | zip 格式 | zip -r a.zip dir/、unzip a.zip -d target/ |
gzip / gunzip | gz 单文件压缩 | gzip file(变 file.gz) |
tar 参数口诀:
c创建、x解压、t查看、z用gzip、v显示过程、f指定文件
8. 系统信息与日志
| 命令 | 说明 | 常用示例 |
|---|---|---|
uname -a | 内核/系统信息 | uname -r(内核版本) |
cat /etc/os-release | 发行版信息 | — |
uptime | 运行时长/负载 | — |
date | 日期时间 | date "+%Y-%m-%d %H:%M:%S" |
journalctl | 查看 systemd 日志 | journalctl -u nginx -f |
dmesg | 内核日志 | `dmesg |
history | 历史命令 | `history |
env | 环境变量 | `env |
which / whereis | 命令位置 | which python |
9. 软件包管理
| 系统 | 命令 | 常用示例 |
|---|---|---|
| Debian/Ubuntu | apt | sudo apt update、sudo apt install nginx、apt search xxx、sudo apt remove xxx |
| CentOS/RHEL | yum / dnf | yum install -y nginx、yum list installed |
| 通用 | systemctl | systemctl start/stop/restart/status/enable nginx |
10. 管道与重定向(解惑重点)
| 符号 | 含义 | 示例 |
|---|---|---|
> | 输出覆盖到文件 | echo hello > a.txt |
>> | 输出追加到文件 | echo world >> a.txt |
2> | 错误输出重定向 | cmd 2> error.log |
2>&1 | 错误合并到标准输出 | cmd > all.log 2>&1 |
| ` | ` | 管道,前输出作后输入 |
&& | 前成功才执行后 | make && make install |
| ` | ` | |
; | 依次执行多条 | cd /tmp; ls |
Ctrl+C | 终止前台进程 | — |
Ctrl+Z | 挂起进程(配合 bg/fg) | — |
Tab | 自动补全 | 敲两下 Tab 列出候选 |
11. 生产实战案例
案例一:凌晨日志盘 100% 告警,10 分钟定位清理
背景:监控告警 /var/log 分区 100%,应用开始报写入失败。
# 1. 找出哪个目录最大(逐层下钻)
du -h --max-depth=1 /var/log | sort -rh | head
# → 发现 /var/log/myapp 占 45G
# 2. 看具体文件
du -sh /var/log/myapp/* | sort -rh | head
# → app-2026-07-*.log 每天 2G,保留 30 天全在
# 3. 止血:清理 7 天前的日志(先确认没有进程句柄问题)
find /var/log/myapp -name "app-*.log" -mtime +7 -delete
df -h /var/log # 确认空间回落
# 4. 治本:配置 logrotate 自动轮转(/etc/logrotate.d/myapp)
# /var/log/myapp/*.log { daily rotate 7 compress missingok copytruncate }
要点:copytruncate 让应用无需重启即可切换日志(复制后清空原文件),避免删文件不释放空间的句柄坑。
案例二:手滑 rm 删错目录后的急救
背景:本想 rm -rf ./tmp,实际打成了 rm -rf ./tmp (后面多了个目录名),删掉了部分业务文件。
# 第一原则:立即停手,不要再往该磁盘写任何数据(写入会覆盖被删数据的块)
# 救援优先级:
1. 有备份 → 直接恢复备份(最快最可靠,日常备份的意义就在这)
2. 无备份但文件被进程占用 → 从 /proc/<PID>/fd 找回:
lsof | grep deleted 找到句柄 → cp /proc/1234/fd/5 /恢复路径
3. 都没有 → 卸载分区用 extundelete / photorec 碰运气(成功率看运气)
# 预防习惯(比救援重要):
- rm 前把路径打全后先按一下 Tab 确认、再 ls 确认目标
- 重要服务器设别名:alias rm='rm -i'
- 用 mv 到 /tmp/trash 代替 rm,定期清理
案例三:批量处理救回发布事故
背景:发布脚本 bug 导致 2000 个 .html 文件被错误生成为 .html.tmp,用户访问 404。
# 1. 先统计影响面
find /var/www/html -name "*.html.tmp" | wc -l # 确认 2000 个
# 2. 抽样验证 1 个文件没问题后,批量改回
find /var/www/html -name "*.html.tmp" -exec sh -c 'mv "$1" "${1%.tmp}"' _ {} \;
# 3. 验证
find /var/www/html -name "*.html.tmp" | wc -l # 应为 0
curl -I http://localhost/index.html # 抽查可访问
要点:批量操作前先 count 看影响面、先处理 1 个验证,确认无误再全量执行。
二、Windows CMD 常用命令
1. 文件与目录
| 命令 | 说明 | 示例 |
|---|---|---|
dir | 列出目录内容 | dir /a(含隐藏)、dir /s *.log(递归找文件) |
cd | 切换目录 | cd C:\Users、cd ..、cd /d D:\work(跨盘符要加 /d) |
md / mkdir | 创建目录 | mkdir test\sub |
copy | 复制文件 | copy a.txt D:\backup\ |
xcopy | 复制目录 | xcopy /s /e /i src dst(含子目录和空目录) |
robocopy | 强大复制(推荐) | robocopy src dst /e /mt:8(多线程) |
move | 移动/重命名 | move old.txt new.txt |
del / erase | 删除文件 | del /f /q *.tmp(强制安静删除) |
rd / rmdir | 删除目录 | rd /s /q dir(递归不确认,谨慎使用) |
ren | 重命名 | ren a.txt b.txt |
type | 查看文件内容 | type log.txt |
where | 查找命令位置 | where python |
2. 系统与进程
| 命令 | 说明 | 示例 |
|---|---|---|
tasklist | 查看进程 | `tasklist |
taskkill | 结束进程 | taskkill /pid 1234 /f、taskkill /im notepad.exe /f |
systeminfo | 系统详细信息 | `systeminfo |
hostname | 主机名 | — |
whoami | 当前用户 | whoami /groups(查看所属组) |
set | 查看/设置环境变量 | set PATH、setx MY_VAR "value"(永久写入) |
echo | 输出/回显 | echo %PATH%、echo hello > a.txt |
cls | 清屏 | — |
shutdown | 关机/重启 | shutdown /s /t 60(60秒后关机)、shutdown /r /t 0(立即重启)、shutdown /a(取消) |
sfc | 系统文件检查 | sfc /scannow(需管理员) |
chkdsk | 磁盘检查 | chkdsk D: /f |
3. 网络
| 命令 | 说明 | 示例 |
|---|---|---|
ipconfig | 查看网络配置 | ipconfig /all、ipconfig /flushdns(清DNS缓存) |
ping | 测试连通性 | ping -t baidu.com(持续ping,Ctrl+C 停止) |
tracert | 路由追踪 | tracert baidu.com |
netstat | 端口与连接 | `netstat -ano |
nslookup | DNS 查询 | nslookup baidu.com |
arp | ARP 缓存 | arp -a |
route | 路由表 | route print |
查端口被谁占用:
netstat -ano | findstr :端口号拿到 PID,再tasklist | findstr PID找进程名。
4. 其他实用
| 命令 | 说明 | 示例 |
|---|---|---|
findstr | 文本搜索(类似grep) | findstr /s /i /n "error" *.log |
tree | 树状目录 | tree /f(含文件) |
attrib | 文件属性 | attrib +h file(设隐藏) |
fc | 文件比较 | fc a.txt b.txt |
certutil | 算文件哈希 | certutil -hashfile file.zip SHA256 |
clip | 输出到剪贴板 | `ipconfig |
5. 生产实战案例
案例一:IIS 站点启动失败,80 端口被"System"占用
背景:Windows 服务器重启后 IIS 站点起不来,提示端口被占用。
# 1. 查 80 端口被谁占用
netstat -ano | findstr :80
# → 最后一列 PID 是 4
tasklist | findstr " 4 "
# → 显示 System 进程(PID 4 是内核,通常是 HTTP.sys 被别的服务占用)
# 2. 常见元凶:SQL Server Reporting Services、Web 部署代理、Skype 等
# 查注册了 URL 的服务
netsh http show servicestate | findstr :80
# 3. 本案例:Reporting Services 占用了 80,停掉并改它的端口,IIS 恢复
net stop "SQL Server Reporting Services"
要点:Windows 下 PID 4 (System) 占端口不要慌,用 netsh http show servicestate 查真正的使用者。
案例二:robocopy 做 Windows 文件服务器每日镜像备份
背景:文件服务器 500G 共享目录需每日备份到备份机,要求只传变化文件。
# 写成 backup.bat,加入计划任务每天 23:00 执行
robocopy D:\share \\backup-server\share_backup /MIR /R:3 /W:10 /LOG+:D:\logs\backup.log /TEE /NP
# 参数说明:
# /MIR 镜像模式(源删了目标也删,想保留历史改用 /E)
# /R:3 失败重试 3 次(默认 100 万次会卡死任务)
# /W:10 重试间隔 10 秒
# /LOG+ 追加日志 /TEE 同时输出到屏幕 /NP 不显示进度(日志干净)
# 计划任务:每天 23:00 跑
schtasks /create /tn "NightlyBackup" /tr "D:\scripts\backup.bat" /sc daily /st 23:00
要点:robocopy 的退出码 0~7 都是成功(8 及以上才是失败),批处理里判断 if %errorlevel% geq 8。
案例三:C 盘告警,快速找出罪魁祸首
# 1. 找出 Windows 目录下大于 500M 的文件
dir C:\ /s /a /o-s 2>nul | more # 慢但全
# 更快:直接查常见的空间杀手
dir C:\Windows\SoftwareDistribution\Download /s # Windows更新缓存(可清)
dir C:\Windows\Temp /s # 临时文件
wevtutil qe System /q:"*[System[(EventID=1074)]]" /f:text /c:5 # 查谁重启过机器
# 2. 清理补丁备份(安全做法)
Dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase
三、PowerShell 常用命令
PowerShell 处理的是"对象"而非纯文本,管道功能更强大。Win10/11 自带 5.1,可装 7.x。
1. 文件操作
| 命令(别名) | 说明 | 示例 |
|---|---|---|
Get-ChildItem(ls/dir/gci) | 列目录 | gci -Recurse -Filter *.log |
Get-Content(cat/type) | 读文件 | cat app.log -Tail 50 -Wait(类似 tail -f) |
Set-Content / Add-Content | 写/追加文件 | `“hello” |
Copy-Item(cp) | 复制 | cp -Recurse src dst |
Move-Item(mv) | 移动/重命名 | mv old new |
Remove-Item(rm/del) | 删除 | rm -Recurse -Force dir |
New-Item(ni) | 新建 | ni -ItemType Directory test |
Get-Location(pwd) | 当前路径 | — |
Test-Path | 判断路径存在 | Test-Path C:\temp |
2. 进程与服务
| 命令 | 说明 | 示例 |
|---|---|---|
Get-Process(ps) | 进程列表 | `ps chrome |
Stop-Process(kill) | 结束进程 | kill -Name notepad -Force |
Get-Service(gsv) | 服务列表 | `gsv |
Restart-Service | 重启服务 | Restart-Service wuauserv(需管理员) |
3. 网络与系统
| 命令 | 说明 | 示例 |
|---|---|---|
Test-NetConnection | 测试端口(超好用) | Test-NetConnection host -Port 443 |
Get-NetIPAddress | IP 地址 | Get-NetIPAddress -AddressFamily IPv4 |
Resolve-DnsName | DNS 查询 | Resolve-DnsName baidu.com |
Invoke-WebRequest(curl/iwr) | HTTP 请求 | iwr https://api.com/data |
Invoke-RestMethod(irm) | REST 请求(自动解析JSON) | irm https://api.com/data |
Get-ComputerInfo | 系统信息 | — |
$env:PATH | 读环境变量 | $env:PATH -split ';'(分行显示) |
Get-History(h) | 历史命令 | — |
4. 管道筛选三板斧
# 过滤:Where-Object(别名 ? / where)
Get-Process | Where-Object { $_.CPU -gt 100 }
# 选列:Select-Object(别名 select)
Get-Process | Select-Object Name, CPU -First 10
# 遍历:ForEach-Object(别名 % / foreach)
gci *.log | ForEach-Object { $_.Name }
5. 实用一行命令
# 大文件排序找前10
gci -Recurse | Sort Length -Desc | Select -First 10 FullName, Length
# 统计目录大小(MB)
"{0:N2} MB" -f ((gci -Recurse | Measure Length -Sum).Sum / 1MB)
# 批量重命名(加前缀)
gci *.txt | Rename-Item -NewName { "new_" + $_.Name }
# 查看文件 MD5/SHA256
Get-FileHash .\file.zip -Algorithm SHA256
# 解压/压缩
Expand-Archive a.zip -DestinationPath .\out
Compress-Archive .\dir\* out.zip
6. 生产实战案例
案例一:批量巡检 50 台 Windows 服务器
背景:月底安全巡检,需要收集 50 台服务器的磁盘余量、关键服务状态、最近重启时间。
# servers.txt 每行一个主机名,用 Invoke-Command 并行收集
$servers = Get-Content .\servers.txt
Invoke-Command -ComputerName $servers -ScriptBlock {
[PSCustomObject]@{
Server = $env:COMPUTERNAME
DiskFreeGB = [math]::Round((Get-PSDrive C).Free / 1GB, 1)
IISStatus = (Get-Service W3SVC -ErrorAction SilentlyContinue).Status
LastBoot = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
}
} | Export-Csv .\report.csv -NoTypeInformation -Encoding UTF8
# 输出 CSV 直接用 Excel 打开交差,异常机器一目了然
要点:Invoke-Command 并行执行,50 台机器秒级完成;前提是 WinRM 已启用(Enable-PSRemoting)。
案例二:服务器半夜重启,从事件日志找原因
背景:应用服务器凌晨 3 点重启,早上业务投诉,需要定性是计划内还是异常。
# 1. 查系统启动与关机事件(System 日志)
Get-WinEvent -FilterHashtable @{LogName='System'; Id=6005,6006,1074,41} -MaxEvents 20 |
Format-Table TimeCreated, Id, Message -AutoSize
# 6005=开机 6006=正常关机 1074=谁发起的重启 41=异常断电/蓝屏
# 2. 若是 41 号事件(Kernel-Power)= 非正常关机,查蓝屏转储
Get-ChildItem C:\Windows\MEMORY.DMP, C:\Windows\Minidump\*.dmp -ErrorAction SilentlyContinue
# 3. 若是 1074,Message 里直接写明哪个进程/用户发起的重启
本案例结论:1074 事件显示是 Windows Update 自动重启(wuauserv 发起)。整改:生产服务器改组策略为"下载后通知安装",禁止自动重启。
案例三:分析 IIS 日志揪出扫描攻击源
# 统计昨天日志里各 IP 的请求量 Top20(IIS 日志是空格分隔)
$log = "C:\inetpub\logs\LogFiles\W3SVC1\u_ex$(Get-Date (Get-Date).AddDays(-1) -Format yyMMdd).log"
Get-Content $log | Where-Object { $_ -notmatch '^#' } |
ForEach-Object { ($_ -split ' ')[8] } | # 第9列是客户端IP
Group-Object | Sort-Object Count -Descending | Select-Object -First 20 Name, Count
# 配合状态码分析:找出产生大量 404 的 IP(扫描器特征)
Get-Content $log | Where-Object { $_ -match ' 404 ' } |
ForEach-Object { ($_ -split ' ')[8] } | Group-Object | Sort Count -Desc | Select -First 10
四、Linux 与 Windows 命令对照表
| 功能 | Linux | Windows CMD | PowerShell |
|---|---|---|---|
| 列目录 | ls | dir | Get-ChildItem / ls |
| 切换目录 | cd | cd / cd /d | cd |
| 当前路径 | pwd | cd(不带参数) | Get-Location |
| 清屏 | clear / Ctrl+L | cls | Clear-Host / cls |
| 查看文件 | cat | type | Get-Content |
| 实时看日志 | tail -f | 无内置 | Get-Content -Wait -Tail 10 |
| 复制 | cp -r | copy / xcopy / robocopy | Copy-Item |
| 移动/重命名 | mv | move / ren | Move-Item / Rename-Item |
| 删除 | rm -rf | del / rd /s /q | Remove-Item -Recurse -Force |
| 建目录 | mkdir -p | mkdir | New-Item -ItemType Directory |
| 文本搜索 | grep -rn | findstr /s /n | Select-String(别名 sls) |
| 查进程 | ps aux | tasklist | Get-Process |
| 杀进程 | kill -9 PID | taskkill /pid PID /f | Stop-Process -Id PID -Force |
| 查端口占用 | ss -tlnp | netstat -ano | Get-NetTCPConnection -State Listen |
| 测试端口 | nc -zv host 80 | telnet host 80 | Test-NetConnection host -Port 80 |
| 查看IP | ip addr | ipconfig | Get-NetIPAddress |
| 下载/请求 | curl / wget | curl.exe(Win10+自带) | Invoke-WebRequest |
| 环境变量 | env / echo $PATH | set / echo %PATH% | $env:PATH |
| 查找命令 | which | where | Get-Command |
| 历史命令 | history | F7 键 | Get-History |
| 软链接 | ln -s | mklink | New-Item -ItemType SymbolicLink |
| 压缩 | tar -zcvf | 无内置 | Compress-Archive |
| 解压 | tar -zxvf | 无内置(tar 新版Win自带) | Expand-Archive |
| 文件哈希 | md5sum / sha256sum | certutil -hashfile | Get-FileHash |
| 定时任务 | crontab -e | schtasks | Register-ScheduledTask |
五、常见场景解惑
Q1:怎么找出磁盘被谁占满了?
# Linux:从根目录一层层找最大的
du -h --max-depth=1 / 2>/dev/null | sort -rh | head -20
# Linux:找出超过 500M 的文件
find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null
# Windows PowerShell:找出当前目录下最大的10个文件
gci -Recurse -File | Sort Length -Desc | Select -First 10 FullName, @{N='SizeMB';E={[math]::Round($_.Length/1MB,2)}}
Q2:端口被占用了怎么办?
# Linux:看 8080 被谁占用
ss -tlnp | grep 8080 # 或 lsof -i :8080
kill -9 <PID>
# Windows CMD 两步走
netstat -ano | findstr :8080 # 拿到最后一列 PID
tasklist | findstr <PID> # 看进程名
taskkill /pid <PID> /f # 杀掉
Q3:后台运行一个程序,关掉终端也不停?
# Linux 方式一:nohup
nohup ./myserver > server.log 2>&1 &
# Linux 方式二:screen / tmux(可随时再进入查看)
tmux new -s work # 新建会话,跑程序
# 按 Ctrl+B 再按 D 脱离;重新进入:tmux attach -t work
Q4:怎么在日志里快速定位错误?
# 找 error 并显示前后各 5 行上下文
grep -n -C 5 "error" app.log
# 实时跟踪日志并过滤关键字
tail -f app.log | grep --line-buffered "ERROR"
# 统计每类错误出现次数
grep "ERROR" app.log | awk '{print $5}' | sort | uniq -c | sort -rn
# PowerShell 实时跟踪+过滤
Get-Content app.log -Wait -Tail 100 | Select-String "ERROR"
Q5:两台机器之间传文件?
# Linux → Linux(scp)
scp ./file.zip user@192.168.1.100:/home/user/
# 整个目录
scp -r ./dir user@192.168.1.100:/home/user/
# Windows → Linux 用 WinSCP(图形界面)或 scp(Win10+ 自带 OpenSSH 客户端)
scp .\file.zip user@192.168.1.100:/home/user/
Q6:批量查找替换文件内容?
# Linux:所有 .go 文件中的 old 替换为 new
grep -rl "old" . --include="*.go" | xargs sed -i 's/old/new/g'
# PowerShell
(gci -Recurse -Filter *.go) | ForEach-Object {
(Get-Content $_.FullName -Raw) -replace 'old','new' | Set-Content $_.FullName
}
Q7:如何查看环境变量并修改?
# Linux 临时生效
export PATH=$PATH:/my/bin
# Linux 永久生效(写入 ~/.bashrc 或 ~/.zshrc)
echo 'export PATH=$PATH:/my/bin' >> ~/.bashrc && source ~/.bashrc
# Windows 临时(仅当前窗口)
set PATH=%PATH%;C:\my\bin
# Windows 永久(用户级)
setx PATH "%PATH%;C:\my\bin" # 注意:setx 有 1024 字符截断风险
# PowerShell 永久(推荐方式)
[Environment]::SetEnvironmentVariable("MY_VAR", "value", "User")
Q8:压缩包相关速查
# Linux
tar -zcvf backup.tar.gz ./dir # 打包压缩
tar -zxvf backup.tar.gz # 解压
tar -zxvf backup.tar.gz -C /tmp # 解压到指定目录
unzip a.zip -d ./out # zip 解压
# Windows(新版自带 tar)
tar -zcvf backup.tar.gz dir
tar -zxvf backup.tar.gz
Q9:查看系统资源占用(卡顿排查)
# Linux 一键看重点
top # 整体情况
free -h # 内存
df -h # 磁盘
iostat -x 1 # IO(需装 sysstat)
# Windows
Get-Process | Sort CPU -Desc | Select -First 10 # CPU 最高的进程
Get-Process | Sort WS -Desc | Select -First 10 # 内存最高的进程
# 或者直接用图形界面:taskmgr / resmon / perfmon
Q10:忘了刚敲过的命令?
# Linux
history | grep ssh # 搜索历史
!123 # 重新执行第123条
Ctrl+R # 交互式反向搜索(神器!)
# PowerShell / CMD
Get-History # PowerShell 历史
# 或按 F7(CMD 中弹窗显示历史)
# Ctrl+R 在 PowerShell 7 / Windows Terminal 中同样可用
附:Git Bash 使用小贴士
你在 Windows 上使用 Git Bash,它提供了一套"Linux 风格"的环境,大部分 Linux 命令可以直接用。
| 特性 | 说明 |
|---|---|
| 路径表示 | Windows 盘符写作 /c/Users/...(C盘)或 /e/DocFile/...(E盘) |
| 可用命令 | ls、grep、find、awk、sed、ssh、scp、curl、vim 等都可用 |
| 混合调用 | 可以直接调用 Windows 程序,如 notepad file.txt、explorer . |
| 注意点 | 路径中的反斜杠需转义或改用正斜杠;某些命令(如 ps、kill)行为和原生 Linux 有差异 |
六、Git 常用命令
1. 初始配置与仓库
| 命令 | 说明 | 常用示例 |
|---|---|---|
git config | 配置用户信息 | git config --global user.name "张三"、git config --global user.email "a@b.com" |
git config -l | 查看所有配置 | git config --global -l |
git init | 初始化本地仓库 | git init |
git clone | 克隆远程仓库 | git clone <url>、git clone -b dev <url>(克隆指定分支)、git clone --depth 1 <url>(浅克隆,只要最新) |
2. 提交相关(日常高频)
| 命令 | 说明 | 常用示例 |
|---|---|---|
git status | 查看工作区状态 | git status -s(简洁模式) |
git diff | 查看改动 | git diff(未暂存的)、git diff --staged(已暂存的)、git diff HEAD~1(与上次提交比) |
git add | 加入暂存区 | git add .(全部)、git add -p(交互式逐块挑选,推荐) |
git commit | 提交 | git commit -m "msg"、git commit -am "msg"(跳过 add 直接提交已跟踪文件) |
git commit --amend | 修改上一次提交 | git commit --amend -m "新消息"(改消息)、漏改了文件时:git add . && git commit --amend --no-edit |
git log | 查看历史 | git log --oneline --graph --all(图形化简洁历史,建议设别名) |
3. 分支管理
| 命令 | 说明 | 常用示例 |
|---|---|---|
git branch | 查看/创建分支 | git branch(列出本地)、git branch -a(含远程)、git branch dev(创建) |
git switch | 切换分支(新命令) | git switch dev、git switch -c feature(创建并切换) |
git checkout | 切换分支(老命令) | git checkout -b feature(创建并切换) |
git merge | 合并分支 | git switch main && git merge dev(把 dev 合进 main) |
git rebase | 变基(让历史成直线) | git rebase main(把当前分支接到 main 最新处)、git rebase -i HEAD~3(交互式整理最近3条提交) |
git branch -d | 删除分支 | git branch -d dev(安全删除)、git branch -D dev(强制删除) |
git push --delete | 删除远程分支 | git push origin --delete feature |
git cherry-pick | 摘取单个提交到当前分支 | git cherry-pick <commit-id> |
推荐别名:
git config --global alias.lg "log --oneline --graph --all --decorate",之后用git lg看历史。
4. 回滚与撤销(解惑重点)
| 场景 | 命令 | 说明 |
|---|---|---|
| 撤销工作区改动(未 add) | git restore <file> | 丢弃文件修改,不可恢复 |
| 取消暂存(已 add 未 commit) | git restore --staged <file> | 仅移出暂存区,改动还在 |
| 撤销最近一次 commit(保留改动) | git reset --soft HEAD~1 | 改动回到暂存区 |
| 撤销最近一次 commit(改动回工作区) | git reset --mixed HEAD~1 | 默认模式,改动未暂存 |
| 撤销最近一次 commit(彻底丢弃) | git reset --hard HEAD~1 | 危险,改动全丢 |
| 回滚到指定提交 | git reset --hard <commit-id> | 之后的提交全部丢弃 |
| 生成一个"反向提交"来撤销 | git revert <commit-id> | 安全,不改历史,已 push 的代码用这个 |
| 找回误删的提交 | git reflog | 查看所有 HEAD 变动记录,再 git reset --hard <id> 救回 |
口诀:代码还没 push 用
reset改历史;已经 push 用revert生成新提交。reflog是后悔药,几乎能找回任何丢失的提交。
5. Stash 暂存
| 命令 | 说明 | 常用示例 |
|---|---|---|
git stash | 暂存当前改动 | git stash 或 git stash push -m "备注" |
git stash -u | 连新文件一起暂存 | -u 包含未跟踪文件 |
git stash list | 查看暂存列表 | — |
git stash pop | 恢复最近一次并删除记录 | 恢复时若有冲突,记录会保留 |
git stash apply | 恢复但不删除记录 | git stash apply stash@{1}(恢复指定的) |
git stash drop | 删除某条记录 | git stash drop stash@{0} |
git stash show | 查看暂存内容 | git stash show -p(看详细 diff) |
典型场景:改到一半要切分支修 bug →
git stash→git switch hotfix→ 修完回来 →git stash pop。
6. 解决冲突
冲突出现在 merge / rebase / stash pop / pull 时,文件会出现冲突标记:
<<<<<<< HEAD
我这边的代码
=======
对方分支的代码
>>>>>>> feature
解决流程:
# 1. 查看哪些文件冲突
git status # 冲突文件标记为 both modified
# 2. 手动编辑文件,删除 <<<<<<<、=======、>>>>>>> 标记,保留正确内容
# 3. 标记为已解决并继续
git add <冲突文件>
git merge --continue # merge 场景(或直接 git commit)
git rebase --continue # rebase 场景
# 中途想放弃,回到冲突前
git merge --abort
git rebase --abort
| 命令 | 说明 |
|---|---|
git checkout --ours <file> | 冲突文件全部采用"我方"版本 |
git checkout --theirs <file> | 冲突文件全部采用"对方"版本 |
git diff --name-only --diff-filter=U | 只列出冲突文件名 |
7. 远程操作
| 命令 | 说明 | 常用示例 |
|---|---|---|
git remote -v | 查看远程地址 | — |
git fetch | 拉取远程更新(不合并) | 先看 git fetch 再 git log HEAD..origin/main --oneline 看差异 |
git pull | 拉取并合并 | git pull --rebase(用变基代替合并,历史更干净) |
git push | 推送 | git push -u origin dev(首次推送并建立跟踪)、git push --force-with-lease(安全的强推,别人有更新时会拒绝) |
git tag | 标签 | git tag v1.0.0、git push origin v1.0.0(推送标签)、git tag -d v1.0.0(删除) |
8. Git 常见场景解惑
Q:commit 消息写错了怎么办?
git commit --amend -m "正确的消息" # 还没 push 时
Q:不小心提交到了错误的分支?
git log --oneline -1 # 记下提交 id,如 a1b2c3
git reset --hard HEAD~1 # 当前分支撤销(改动还在 reflog 里)
git switch 正确的分支
git cherry-pick a1b2c3 # 把提交摘过来
Q:本地改乱了,想完全回到远程状态?
git fetch origin
git reset --hard origin/main # 丢弃所有本地提交和改动,慎用
Q:只想拉远程某个文件覆盖本地?
git fetch
git checkout origin/main -- path/to/file
9. Git 生产实战案例
案例一:生产紧急 hotfix,但本地有一堆未完成的改动
背景:正在 feature 分支开发新功能(改动未提交、还跑不通),线上突然报 bug 必须立刻修复。
# 1. 当前改动先 stash 封存(未跟踪的新文件也要,加 -u)
git stash push -u -m "feature开发到一半"
# 2. 从 main 拉 hotfix 分支修复
git switch main && git pull
git switch -c hotfix/order-null-fix
# ... 修复代码 ...
git commit -am "fix: 修复订单空指针"
# 3. 推 hotfix 分支走紧急评审合并上线
git push -u origin hotfix/order-null-fix
# 4. 回到原来的开发分支,恢复现场继续干活
git switch feature/order-v2
git stash pop # 改动回来了,无缝衔接
git stash list # 确认 stash 已清空
要点:stash 是上下文的保险箱,任何“临时被打断”的场景都不要硬切分支(未提交改动会被带过去污染)。
案例二:误删分支 + 强推丢失提交,reflog 全部找回
背景:新人执行了 git branch -D feature/pay,又 git push -f 覆盖了远程,两天的提交全没了。
# 1. reflog 是 HEAD 的全程录像,删分支也留痕
git reflog
# → 找到 feature/pay 最后一次提交 id:a3f8c2d
# 2. 现场重建分支(提交原封不动回来)
git branch feature/pay a3f8c2d
git switch feature/pay && git log --oneline -5 # 确认提交都在
# 3. 重新推送(正常 push,不要再强推)
git push origin feature/pay
要点:Git 里几乎删不掉东西——只要提交存在过,reflog 默认保留 90 天。出事先别慌,git reflog 永远是你最后的底牌。团队规范上应禁用 --force,只允许 --force-with-lease。
七、Docker 常用命令
1. 镜像(Image)操作
| 命令 | 说明 | 常用示例 |
|---|---|---|
docker images | 列出本地镜像 | docker images(含标签和大小) |
docker pull | 拉取镜像 | docker pull nginx:1.25、docker pull ubuntu:22.04 |
docker build | 构建镜像 | docker build -t myapp:1.0 .(当前目录 Dockerfile) |
docker rmi | 删除镜像 | docker rmi nginx:1.25、docker rmi -f <id>(强制) |
docker tag | 打标签 | docker tag myapp:1.0 registry.com/myapp:1.0 |
docker push | 推送镜像 | docker push registry.com/myapp:1.0 |
docker save / load | 导出/导入镜像(离线搬运) | docker save -o myapp.tar myapp:1.0、docker load -i myapp.tar |
docker history | 查看镜像分层 | docker history myapp:1.0(排查镜像为什么大) |
docker search | 搜索 Docker Hub | docker search nginx |
2. 容器(Container)生命周期
| 命令 | 说明 | 常用示例 |
|---|---|---|
docker run | 创建并启动容器 | 见下方常用参数 |
docker ps | 查看运行中的容器 | docker ps -a(含已停止的)、docker ps -q(只显示 ID) |
docker stop / start / restart | 停止/启动/重启 | docker stop mynginx、docker start -a mynginx(启动并显示输出) |
docker rm | 删除容器 | docker rm mynginx、docker rm -f mynginx(运行中强删) |
docker rename | 重命名容器 | docker rename old new |
docker stats | 实时资源占用 | docker stats(类似 top,Ctrl+C 退出) |
docker inspect | 查看容器/镜像详情 | docker inspect mynginx(IP、挂载、环境变量全在这) |
docker run 高频参数:
docker run -d \ # -d 后台运行
--name mynginx \ # 容器命名
-p 8080:80 \ # 端口映射:宿主机:容器
-v /host/data:/container/data \ # 目录挂载:宿主机:容器
-e TZ=Asia/Shanghai \ # 环境变量
--restart unless-stopped \ # 重启策略(开机自起,除非手动停)
nginx:1.25
# 其他常用:
# -it 交互式终端(配合 /bin/bash 调试镜像)
# --rm 退出后自动删除(一次性调试容器)
# --network host 使用宿主机网络
docker run -it --rm ubuntu:22.04 /bin/bash # 临时进个干净环境调试
3. 日志与排错
| 命令 | 说明 | 常用示例 |
|---|---|---|
docker logs | 查看容器日志 | docker logs mynginx |
docker logs -f | 实时跟踪日志 | docker logs -f --tail 100 mynginx(从最后100行开始跟踪) |
docker logs --since | 按时间过滤 | docker logs --since 30m mynginx(最近30分钟) |
docker top | 查看容器内进程 | docker top mynginx |
docker port | 查看端口映射 | docker port mynginx |
docker events | 实时事件流 | docker events(排查容器为什么反复重启) |
4. exec 进入容器(高频)
# 进入运行中的容器(最常用)
docker exec -it mynginx /bin/bash
# 没有 bash 的精简镜像(如 alpine)用 sh
docker exec -it mynginx /bin/sh
# 不进入容器,直接执行单条命令
docker exec mynginx ls /etc/nginx
docker exec -e KEY=val mynginx env # 带环境变量执行
# 以 root 身份进入(容器默认用户权限不够时)
docker exec -it -u root mynginx /bin/bash
| 命令 | 说明 | 常用示例 |
|---|---|---|
docker cp | 容器与宿主机互拷文件 | docker cp mynginx:/var/log/nginx ./logs(拷出)、docker cp ./conf mynginx:/etc/(拷入) |
5. 清理磁盘(解惑重点)
Docker 用久了磁盘膨胀,按下面的顺序清理:
| 命令 | 说明 | 影响范围 |
|---|---|---|
docker system df | 查看 Docker 磁盘占用 | 只查看,不删除 |
docker container prune | 删除所有已停止的容器 | 运行中的不受影响 |
docker image prune | 删除悬空镜像(<none>) | 有标签的镜像不受影响 |
docker image prune -a | 删除所有未被容器使用的镜像 | 注意:本地没用到的镜像全删 |
docker volume prune | 删除未使用的数据卷 | 可能有数据,先确认 |
docker system prune | 一键清理(容器+网络+悬空镜像) | 常用 |
docker system prune -a --volumes | 全量深度清理 | 最彻底也最危险,相当于重置 |
6. docker-compose(多容器编排)
新版为插件形式
docker compose(无连字符),老版是独立命令docker-compose,两者参数一致。配置写在docker-compose.yml。
| 命令 | 说明 | 常用示例 |
|---|---|---|
docker compose up | 启动所有服务 | docker compose up -d(后台启动,最常用) |
docker compose up --build | 重新构建并启动 | 改了代码/Dockerfile 后使用 |
docker compose down | 停止并删除容器、网络 | docker compose down -v(连数据卷一起删,谨慎) |
docker compose ps | 查看服务状态 | — |
docker compose logs | 查看日志 | docker compose logs -f web(跟踪指定服务) |
docker compose exec | 进入服务容器 | docker compose exec web bash(web 是 yml 里的服务名,不是容器名) |
docker compose restart | 重启服务 | docker compose restart web |
docker compose stop / start | 停止/启动(不删容器) | — |
docker compose pull | 拉取最新镜像 | — |
docker compose config | 校验并查看最终配置 | 排查 yml 写错时先跑这个 |
最小 docker-compose.yml 示例:
services:
web:
image: nginx:1.25
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
restart: unless-stopped
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
7. Docker 常见场景解惑
Q:容器一启动就退出(Exited)?
docker ps -a # 看退出码,如 Exited (1)
docker logs <容器> # 第一优先:看日志找报错
# 常见原因:主进程结束(容器的生命 = 主进程的生命),可用 -it 手动运行排查
docker run -it --rm <镜像> /bin/sh
Q:容器里改的代码,容器删了还在吗?
不在。容器层随 docker rm 一起删除。需要持久化的数据必须挂载:-v 宿主路径:容器路径 或使用 named volume(如上面 mysql 的 db_data)。
Q:怎么进入数据库容器操作 MySQL?
docker exec -it mysql容器 mysql -uroot -p
# 或导出备份
docker exec mysql容器 mysqldump -uroot -p密码 dbname > backup.sql
Q:镜像里有 <none> 的镜像是什么?
是构建过程中产生的悬空镜像(旧版本被新 tag 覆盖后剩下的),docker image prune 可安全清理。
Q:忘记容器名/记不清全名?
docker ps -a 看到容器 ID 的前几位即可代替全名使用,如 docker logs -f 3a2b。容器名也支持前缀匹配之外的唯一 ID 简写。
8. Docker 生产实战案例
案例一:/var/lib/docker 撑爆磁盘,元凶是容器日志
背景:服务器磁盘 95% 告警,查下来 Docker 占了 80G,但镜像明明只有 10G。
# 1. 看 Docker 磁盘分布
docker system df -v | head -40
# 2. 定位到大头:containers 层占用 60G → 逐容器查日志文件
du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -rh | head
# → 某容器 json.log 单文件 35G(应用 DEBUG 日志狂喷)
# 3. 止血:清空日志文件(不要 rm,文件被占用删了不释放空间)
truncate -s 0 /var/lib/docker/containers/<id>/<id>-json.log
# 4. 治本:全局限制日志大小,/etc/docker/daemon.json
# { "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" } }
systemctl reload docker # 只对新创建的容器生效!
要点:Docker 默认日志无上限轮转,生产必配 max-size;改了 daemon.json 只对新建容器生效,老容器要重建才应用。
案例二:容器里定时任务提前 8 小时执行
背景:报表任务应每天 8:00 跑,实际凌晨 0:00 就执行了——容器内是 UTC 时区。
# 排查:进容器看时间
docker exec myapp date # 显示 UTC,比北京时间晚 8 小时
# 修复方式一:运行参数注入时区(最简单)
docker run -e TZ=Asia/Shanghai -v /etc/localtime:/etc/localtime:ro ...
# 修复方式二:docker-compose
# environment:
# - TZ=Asia/Shanghai
# 验证
docker exec myapp date # 显示 CST 东八区
要点:官方镜像默认 UTC。时间相关应用(定时任务/日志时间戳/证书校验)上线第一件事就是校时。
八、Kubernetes 常用命令
kubectl操作的是集群资源。几乎所有命令都可以加-n <namespace>指定命名空间,不加则操作default。建议设别名:alias k=kubectl。
1. 上下文与命名空间
| 命令 | 说明 | 常用示例 |
|---|---|---|
kubectl config get-contexts | 查看所有集群上下文 | 多集群切换前先确认当前在哪 |
kubectl config use-context | 切换集群 | kubectl config use-context prod-cluster(切生产前一定看清!) |
kubectl config current-context | 当前上下文 | — |
kubectl get ns | 查看命名空间 | — |
kubectl config set-context --current --namespace=xxx | 默认进入某 namespace | 设完后该窗口的命令都不用加 -n 了 |
2. 资源查看(Pod / Deployment / Service)
| 命令 | 说明 | 常用示例 |
|---|---|---|
kubectl get pods | 查看 Pod | kubectl get pods -n prod、-o wide(显示节点和IP)、--watch 或 -w(实时刷新) |
kubectl get deploy | 查看 Deployment | kubectl get deploy -o wide |
kubectl get svc | 查看 Service | kubectl get svc(看 ClusterIP / NodePort / 端口映射) |
kubectl get all | 查看主要资源全家桶 | kubectl get all -n prod |
kubectl get pods -A | 所有命名空间的 Pod | 排查系统组件异常时常用 |
kubectl get pods --field-selector | 按条件筛选 | kubectl get pods -A --field-selector=status.phase!=Running(找出所有非运行的 Pod) |
kubectl get pods -l | 按标签筛选 | kubectl get pods -l app=nginx |
kubectl get nodes | 查看节点 | kubectl get nodes -o wide |
kubectl top | 资源占用(需 metrics-server) | kubectl top pods -n prod、kubectl top nodes |
Pod 状态速读:
Running正常;Pending没调度上;CrashLoopBackOff反复崩溃;ImagePullBackOff镜像拉不下来;Completed一次性任务跑完。
3. 日志查看
| 命令 | 说明 | 常用示例 |
|---|---|---|
kubectl logs | 查看 Pod 日志 | kubectl logs <pod> |
kubectl logs -f | 实时跟踪 | kubectl logs -f <pod> --tail=100 |
kubectl logs -c | 指定容器(多容器 Pod 必加) | kubectl logs <pod> -c <容器名> |
kubectl logs --previous | 看上一次崩溃前的日志 | 排查 CrashLoopBackOff 的关键命令 |
kubectl logs deploy/xxx | 直接看 Deployment 下日志 | kubectl logs -f deploy/myapp --tail=50 |
kubectl logs --since | 按时间过滤 | kubectl logs --since=10m <pod> |
kubectl logs -l | 按标签批量看 | kubectl logs -l app=nginx --tail=20 |
4. exec 进入容器
# 进入 Pod 中的容器(最常用)
kubectl exec -it <pod> -- /bin/bash
# 精简镜像没有 bash 时用 sh
kubectl exec -it <pod> -- /bin/sh
# 多容器 Pod 必须指定容器名
kubectl exec -it <pod> -c <容器名> -- /bin/bash
# 不进入,直接执行单条命令
kubectl exec <pod> -- ls /app
kubectl exec <pod> -- env # 看环境变量是否注入正确
进入容器后排查网络:
curl localhost:8080/health(探活)、cat /etc/resolv.conf(DNS)、wget -qO- <svc名>:<端口>(测 Service 连通性)。
5. describe 排错(重点)
describe 是 K8s 排错第一入口,重点看最下面的 Events(事件)区域,报错原因基本都写在那里:
kubectl describe pod <pod> -n prod
kubectl describe deploy <name>
kubectl describe node <节点名> # 节点压力大/资源不足时看
常见 Events 报错对照:
| Events 中的提示 | 原因 |
|---|---|
FailedScheduling ... Insufficient cpu/memory | 集群资源不够调度,加节点或降 request |
ErrImagePull / ImagePullBackOff | 镜像名/标签错误、仓库无权限(缺 imagePullSecret) |
Back-off restarting failed container | 容器启动就崩,用 logs --previous 看原因 |
Liveness probe failed | 存活探针失败,应用健康检查接口或启动太慢 |
FailedMount | 挂载的 ConfigMap/Secret/PVC 不存在或没就绪 |
6. port-forward 端口转发
# 把本地 8080 转发到 Pod 的 80(调试用,无需改 Service)
kubectl port-forward <pod> 8080:80
# 转发 Service(推荐,会负载到后端任一 Pod)
kubectl port-forward svc/myapp 8080:80
# 转发 Deployment
kubectl port-forward deploy/myapp 8080:80
# 转发后另开终端访问:curl localhost:8080
典型场景:数据库服务只在集群内可达,本地
kubectl port-forward svc/mysql 3306:3306后,用本地 Navicat 连127.0.0.1:3306。
7. 发布与回滚(rollout)
| 命令 | 说明 | 常用示例 |
|---|---|---|
kubectl rollout status | 查看发布进度 | kubectl rollout status deploy/myapp |
kubectl rollout history | 查看发布历史 | kubectl rollout history deploy/myapp |
kubectl rollout undo | 回滚到上一版本 | kubectl rollout undo deploy/myapp |
kubectl rollout undo --to-revision | 回滚到指定版本 | kubectl rollout undo deploy/myapp --to-revision=2 |
kubectl rollout restart | 滚动重启(不更新镜像) | 改了 ConfigMap/Secret 后让它生效 |
kubectl set image | 更新镜像触发发布 | kubectl set image deploy/myapp myapp=myrepo/myapp:v2 |
典型发布流程:
kubectl set image deploy/myapp myapp=myrepo/myapp:v2 # 1. 更新镜像
kubectl rollout status deploy/myapp # 2. 盯发布进度
kubectl get pods -w # 观察新 Pod 起来、旧 Pod 销毁
# 出问题立刻回滚:
kubectl rollout undo deploy/myapp
8. 创建、修改与删除
| 命令 | 说明 | 常用示例 |
|---|---|---|
kubectl apply -f | 应用 yaml(增改通用,推荐) | kubectl apply -f deploy.yaml、-f ./dir/(整个目录) |
kubectl delete -f | 按 yaml 删除 | kubectl delete -f deploy.yaml |
kubectl scale | 扩缩容 | kubectl scale deploy/myapp --replicas=3 |
kubectl edit | 在线编辑资源 | kubectl edit deploy/myapp(改完立即生效) |
kubectl delete pod | 删 Pod(Deployment 会自动重建) | 想让应用"重启"最简单的方式就是删 Pod |
kubectl cp | 本地与 Pod 互拷文件 | kubectl cp ./file <pod>:/tmp/ |
kubectl explain | 查看资源字段说明 | kubectl explain deployment.spec.replicas(忘字段时查) |
kubectl api-resources | 查看所有资源类型及缩写 | 查 deploy、svc、po、ing 这些缩写 |
9. K8s 常见场景解惑
Q:Pod 一直 Pending 起不来?
kubectl describe pod <pod>
# 看 Events:多半是资源不足(Insufficient cpu)或 PVC 未绑定、污点调度问题
Q:Pod 反复重启(CrashLoopBackOff)?
kubectl logs <pod> --previous # 看崩溃前日志,十有八九是应用报错
kubectl describe pod <pod> # 看退出码和探针失败记录
kubectl get pod <pod> -o yaml | grep -A5 lastState # 看上次退出原因
Q:改了 ConfigMap,应用没生效?
挂载为环境变量的 ConfigMap 不会热更新,需重启:kubectl rollout restart deploy/myapp;挂载为文件的会自动更新(有约1分钟延迟),但应用需自己监听文件变化。
Q:Service 创建了但访问不通?
kubectl get endpoints <svc名> # 为空 = 没有匹配到 Pod,检查 selector 标签
kubectl describe svc <svc名> # 核对 selector 与 Pod 的 label 是否一致
# 进入某个 Pod 测试:wget -qO- <svc名>:<port>
Q:如何临时在集群里起个调试容器?
kubectl run debug --rm -it --image=busybox:1.28 -- sh
# 进去后可 nslookup <svc>、wget 测连通性,退出自动删除
10. K8s 生产实战案例
案例一:滚动更新卡死,新老版本各占一半
背景:发布新版本后 rollout status 卡住不动,kubectl get pods 显示 2 个老 Pod Running、2 个新 Pod 一直 not ready。
# 1. 看新 Pod 为什么没就绪
describe=$(kubectl get pods -l app=myapp --sort-by=.metadata.creationTimestamp | tail -1 | awk '{print $1}')
kubectl describe pod $describe | tail -20
# → Events: Readiness probe failed: Get http://:8080/health: connection refused
# 2. 看应用日志,确认是启动慢还是起不来
kubectl logs $describe --tail=50
# → 应用在初始化缓存,需要 90 秒才监听端口,但探针 10 秒就开始探
# 3. 决策:不是代码问题,是探针参数太激进。回滚 or 修探针?
# 业务高峰期 → 先回滚止损:
kubectl rollout undo deploy/myapp
kubectl rollout status deploy/myapp # 确认老版本全部恢复
# 4. 事后修复探针再发布:initialDelaySeconds: 60 或改用 startupProbe
要点:滚动更新保护机制(maxUnavailable)保证了老 Pod 不撤,业务其实没断——遇到发布卡住先别慌着删 Pod,看清探针失败原因再决定回滚还是放行。
案例二:Java 应用 Pod 频繁 OOMKilled
背景:Pod 每隔几小时重启一次,kubectl get pods 的 RESTARTS 不断增长,日志看不到任何异常。
# 1. 看上次退出原因(关键!应用日志是看不到的,因为是内核直接杀)
kubectl get pod <pod> -o jsonpath='{.status.containerStatuses[0].lastState}'
# → {"terminated":{"exitCode":137,"reason":"OOMKilled"}}
# 2. 看内存 limit 与实际用量
kubectl top pod <pod>
kubectl get pod <pod> -o jsonpath='{.spec.containers[0].resources}'
# → limit 512Mi,但 JVM 默认堆是物理内存的 1/4(按节点内存算!)
# 3. 修复:JVM 参数适配容器限制 + 适当调大 limit
# 老版本 JDK 用 -Xmx400m;JDK 8u191+/11+ 用 -XX:MaxRAMPercentage=75
要点:exitCode 137 = OOMKilled,JVM 老版本读的是宿主机内存而非容器 limit,堆上限必须显式设置,否则 limit 形同虚设。
九、数据库常用命令
1. MySQL:登录与退出
| 命令 | 说明 | 常用示例 |
|---|---|---|
mysql -u root -p | 本地登录 | 回车后输密码(密码不写命令行,避免留在 history) |
mysql -h 主机 -P 端口 -u 用户 -p | 远程登录 | mysql -h 192.168.1.10 -P 3306 -u app -p |
mysql -u root -p -e "SQL" | 不进交互直接执行 | mysql -uroot -p -e "SHOW DATABASES;" |
exit / quit / \q | 退出 | — |
命令行直接跟密码:
-p123456(注意 -p 和密码之间不能有空格),方便但不安全。
2. MySQL:库与表操作(交互模式内)
| SQL | 说明 |
|---|---|
SHOW DATABASES; | 查看所有库 |
CREATE DATABASE db DEFAULT CHARSET utf8mb4; | 建库(务必指定 utf8mb4,避免中文乱码) |
USE db; / SELECT DATABASE(); | 切换库 / 查看当前所在库 |
SHOW TABLES; | 查看当前库所有表 |
DESC 表名; / SHOW COLUMNS FROM 表名; | 查看表结构 |
SHOW CREATE TABLE 表名\G | 看建表语句(\G 竖排显示,看长语句更清晰) |
SHOW TABLE STATUS LIKE '表名'\G | 看表大小、行数、引擎 |
DROP DATABASE db; | 删库(不可恢复,慎重) |
3. MySQL:备份与恢复(mysqldump)
# 备份单个库(最常用)
mysqldump -u root -p dbname > dbname_backup.sql
# 备份指定表
mysqldump -u root -p dbname table1 table2 > tables.sql
# 备份所有库
mysqldump -u root -p --all-databases > all.sql
# 只导结构不导数据(-d)
mysqldump -u root -p -d dbname > schema.sql
# 只导数据不导结构(-t)
mysqldump -u root -p -t dbname > data.sql
# 带条件导出(比如只导最近的数据)
mysqldump -u root -p dbname orders --where="create_time>'2026-01-01'" > orders.sql
# 备份并压缩(大库推荐)
mysqldump -u root -p dbname | gzip > dbname_$(date +%F).sql.gz
# 恢复
mysql -u root -p dbname < dbname_backup.sql
zcat dbname.sql.gz | mysql -u root -p dbname # 压缩包直接恢复
4. MySQL:数据导入导出(CSV)
-- 导出查询结果为 CSV(文件在 MySQL 服务器上,需 secure_file_priv 权限)
SELECT * FROM orders
INTO OUTFILE '/var/lib/mysql-files/orders.csv'
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n';
-- 从 CSV 导入
LOAD DATA INFILE '/var/lib/mysql-files/orders.csv'
INTO TABLE orders
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS; -- 跳过表头
客户端侧导出更简单的办法:
mysql -u root -p -e "SELECT * FROM db.orders" db | sed 's/\t/,/g' > out.csv
5. MySQL:用户与权限
-- 查看当前用户及所有用户
SELECT USER(), CURRENT_USER();
SELECT user, host FROM mysql.user;
-- 创建用户(% 表示允许任意主机连接,生产建议限定 IP 段)
CREATE USER 'app'@'%' IDENTIFIED BY 'Strong@123';
-- 授权:只给需要的库的最小权限
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'%';
FLUSH PRIVILEGES;
-- 查看某用户的权限
SHOW GRANTS FOR 'app'@'%';
-- 改密码 / 删用户
ALTER USER 'app'@'%' IDENTIFIED BY 'NewPass@456';
DROP USER 'app'@'%';
6. MySQL:排错与性能常用 SQL
| SQL | 说明 |
|---|---|
SHOW PROCESSLIST; | 查看当前连接与正在执行的 SQL(卡顿时第一眼看这里) |
KILL <id>; | 杀掉指定连接(id 来自 processlist) |
SHOW VARIABLES LIKE 'max_connections'; | 查配置项(换成 wait_timeout 等可查别的) |
SHOW STATUS LIKE 'Threads_connected'; | 当前连接数 |
EXPLAIN SELECT ...; | 看 SQL 执行计划,重点看 type 列:ALL 全表扫描要警惕,至少到 range/ref |
SHOW INDEX FROM 表名; | 查看表上的索引 |
SELECT * FROM information_schema.INNODB_TRX\G | 查看未提交的事务(锁等待排查) |
SHOW ENGINE INNODB STATUS\G | InnoDB 状态大全(死锁日志在里面) |
-- 查看各表占用空间 Top 10
SELECT table_name, table_rows,
ROUND(data_length/1024/1024, 2) AS data_mb,
ROUND(index_length/1024/1024, 2) AS index_mb
FROM information_schema.tables
WHERE table_schema = 'dbname'
ORDER BY data_length DESC LIMIT 10;
7. Redis-cli:连接与基础
| 命令 | 说明 | 常用示例 |
|---|---|---|
redis-cli | 连接本地默认 6379 | — |
redis-cli -h 主机 -p 端口 -a 密码 | 远程连接 | 密码也可连上后用 AUTH 密码 输入(更安全) |
redis-cli -n 2 | 指定 db 编号 | Redis 默认 16 个库(0~15) |
PING | 测试连通 | 返回 PONG 即正常 |
SELECT 2 | 切换 db | — |
INFO | 服务器信息 | INFO memory(内存)、INFO clients(连接数)、INFO keyspace(各库 key 数) |
DBSIZE | 当前库 key 数量 | — |
FLUSHDB / FLUSHALL | 清空当前库 / 所有库 | 生产环境禁用级危险 |
8. Redis-cli:Key 通用操作
| 命令 | 说明 | 示例 |
|---|---|---|
KEYS pattern | 按模式查 key | KEYS user:*(生产禁用,会阻塞全库扫描,用 SCAN 替代) |
SCAN cursor | 渐进式遍历(生产安全) | SCAN 0 MATCH user:* COUNT 100 |
TYPE key | 查看 key 类型 | 返回 string/hash/list/set/zset |
EXISTS key | 是否存在 | — |
TTL key | 剩余过期时间(秒) | -1 永不过期,-2 不存在 |
EXPIRE key 秒 | 设置过期时间 | EXPIRE session:123 3600 |
PERSIST key | 移除过期时间 | — |
DEL key | 删除 key | DEL a b c(可多个) |
RENAME key newkey | 改名 | — |
MEMORY USAGE key | 查看 key 占内存 | 排查大 key |
9. Redis-cli:五种数据类型操作
# String(缓存、计数器)
SET name "tom" # 写入
GET name # 读取
SET name "tom" EX 60 # 写入并设60秒过期
SETNX lock:order 1 # 不存在才写入(分布式锁基础)
INCR counter / DECR counter # 自增自减
MSET a 1 b 2 / MGET a b # 批量读写
# Hash(存对象)
HSET user:1 name tom age 20 # 写字段
HGET user:1 name # 读单字段
HGETALL user:1 # 读全部字段
HINCRBY user:1 age 1 # 字段自增
# List(队列、最新消息列表)
LPUSH queue task1 # 左入队
RPOP queue # 右出队(配合 LPUSH = 队列)
LRANGE queue 0 -1 # 查看全部(0 -1 = 从头到尾)
LLEN queue # 长度
# Set(去重集合、共同好友)
SADD tags:post1 go redis # 添加
SMEMBERS tags:post1 # 查看全部
SISMEMBER tags:post1 go # 是否成员
SINTER set1 set2 # 交集
# ZSet(排行榜)
ZADD rank 100 "tom" 85 "jerry" # 写入(分数 成员)
ZRANGE rank 0 -1 WITHSCORES # 按分数升序看全部
ZREVRANGE rank 0 9 WITHSCORES # 降序 Top10(排行榜)
ZINCRBY rank 5 "tom" # 加分
ZRANK rank "tom" # 查排名
10. Redis 常见场景解惑
Q:生产环境想找某类 key 怎么办?
绝不用 KEYS *(数据量大时会阻塞整个 Redis),用 SCAN:
SCAN 0 MATCH session:* COUNT 100 # 返回下一游标,用返回值继续扫,直到返回 0
# 命令行一次性扫描所有匹配:
redis-cli --scan --pattern 'session:*' | head -100
Q:内存快满了怎么排查?
INFO memory # 看 used_memory_human 和 maxmemory
redis-cli --bigkeys # 扫描大 key(官方工具,边采样边扫,安全)
MEMORY USAGE <key> # 确认某个可疑 key 的大小
Q:key 忘了设过期时间,怎么批量补?
# 配合管道批量设置(示例:给所有 session: 开头的 key 设 24 小时)
redis-cli --scan --pattern 'session:*' | xargs -L1 redis-cli EXPIRE 86400
Q:怎么实时监控 Redis 在干什么?
redis-cli MONITOR # 打印所有执行的命令(调试可用,生产慎用影响性能)
redis-cli --stat # 持续输出请求数/连接数/内存概况(生产安全)
SLOWLOG GET 10 # 查看最近10条慢查询
11. 数据库生产实战案例
案例一:高峰期全站卡顿,一条没加索引的 SQL 拖垮全库
背景:晚高峰页面全面超时,应用无报错,CPU 在数据库服务器上打满。
-- 1. 现场抓正在执行的 SQL(第一证据)
SHOW FULL PROCESSLIST;
-- → 几十条同样的查询,Time 都在 20+ 秒,State = Sending data
-- SELECT * FROM orders WHERE user_phone = '138xxxx' ORDER BY create_time DESC
-- 2. 看执行计划
EXPLAIN SELECT * FROM orders WHERE user_phone = '138xxxx';
-- → type: ALL(全表扫描),rows: 800万,key: NULL(没走任何索引)
-- 3. 止血:先杀掉堆积的查询让业务恢复
KILL 12834; KILL 12835; -- ...(或写脚本批量杀同模式查询)
-- 4. 治本:加索引(800 万行表在线加,MySQL 5.6+ 支持 ONLINE DDL 不锁表)
ALTER TABLE orders ADD INDEX idx_user_phone (user_phone);
-- 5. 验证
-- EXPLAIN 再看 type 变成 ref,rows 降到个位数,页面恢复
要点:数据库 CPU 打满先 SHOW PROCESSLIST 抓现场;EXPLAIN 的 type=ALL + rows 巨大 = 索引缺失铁证。事后把慢查询纳入 long_query_time=1 慢日志日常巡检。
案例二:Redis 内存 100%,缓存大面积失效
背景:应用突然大量穿透到数据库,Redis 监控显示 used_memory 打满 maxmemory。
# 1. 找大 key(官方安全工具)
redis-cli --bigkeys
# → 发现 key "rank:all_users" 是 2.8G 的 ZSet(500万成员,全量用户排行榜)
# 2. 看内存策略
CONFIG GET maxmemory-policy
# → noeviction(默认:满了直接拒绝写入!这就是缓存写不进的原因)
# 3. 止血:改策略让缓存可淘汰
CONFIG SET maxmemory-policy allkeys-lru # 所有 key 按 LRU 淘汰
# (CONFIG SET 即时生效,但要写进 redis.conf 才能重启后保留)
# 4. 治本:大 key 拆分(rank:all_users → 按月分 rank:202607 等)+ 只存 TopN
要点:noeviction 满后写入直接报错而非淘汰,生产缓存场景一般选 allkeys-lru;大 key 必须拆分,单 key 超 1G 就是定时炸弹。
十、Nginx 常用操作
1. 配置文件结构
/etc/nginx/
├── nginx.conf # 主配置(一般不动,只 include 子配置)
├── conf.d/*.conf # 推荐:每个站点一个 conf 放这里
└── sites-enabled/ # Debian/Ubuntu 风格的站点目录
主配置整体层级(指令只能在对应层级中使用):
user nginx; # 运行用户
worker_processes auto; # 工作进程数,auto = CPU核数
error_log /var/log/nginx/error.log; # 全局错误日志
events {
worker_connections 1024; # 每个进程最大连接数
}
http { # HTTP 全局设置
include /etc/nginx/mime.types;
sendfile on;
keepalive_timeout 65;
client_max_body_size 50m; # 上传大小限制(413 报错就改它)
access_log /var/log/nginx/access.log;
include /etc/nginx/conf.d/*.conf; # 加载各站点配置
}
2. server 与 location 常用配置
server {
listen 80; # 监听端口
server_name api.example.com; # 域名(可多个空格分隔,支持 * 泛域名)
root /var/www/html; # 站点根目录
index index.html;
# 静态资源 + 缓存
location /static/ {
alias /data/static/; # 注意 root 与 alias 的路径拼接区别
expires 7d; # 浏览器缓存7天
}
# location 匹配优先级:= > ^~ > 正则(~ / ~*) > 普通前缀
location = /healthz { # 精确匹配(最高优先)
return 200 'ok'; # 直接返回内容,常用于健康检查
}
location ~ \.(js|css|png)$ { # 正则匹配(区分大小写,~* 不区分)
expires 30d;
}
location / { # 普通前缀(最低优先,兜底)
try_files $uri $uri/ /index.html; # SPA 单页应用必配(防止刷新404)
}
}
| 常见指令 | 说明 | 示例 |
|---|---|---|
return | 直接返回状态/跳转 | return 301 https://$host$request_uri;(HTTP 跳 HTTPS) |
rewrite | URL 重写 | rewrite ^/old/(.*)$ /new/$1 permanent; |
try_files | 按顺序尝试文件,最后用兜底 | try_files $uri /index.html; |
deny / allow | IP 访问控制 | allow 192.168.1.0/24; deny all; |
limit_req_zone | 限流 | 配合 limit_req 限制请求频率 |
root与alias易混淆:location /static/ { root /data; }实际找/data/static/xx;alias /data/static/;则直接找/data/static/xx(去掉了 location 前缀)。
3. 反向代理与负载均衡
反向代理(把请求转发给后端应用):
location /api/ {
proxy_pass http://127.0.0.1:8080/; # 末尾带 / 会替换掉 /api/ 前缀
# 透传客户端真实信息(后端拿到真实 IP 的关键)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 超时设置(后端慢导致 504 时调大)
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
}
# WebSocket 代理(多了两行 Upgrade 头)
location /ws/ {
proxy_pass http://127.0.0.1:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
负载均衡(upstream 定义一组后端):
upstream backend {
# 默认轮询(round-robin)
server 192.168.1.11:8080;
server 192.168.1.12:8080 weight=2; # weight 权重,流量2倍
server 192.168.1.13:8080 backup; # backup 备用,其他挂了才启用
server 192.168.1.14:8080 max_fails=3 fail_timeout=30s; # 30秒内失败3次则摘除
# 其他策略(按需选一):
# least_conn; # 最少连接(后端耗时不均时推荐)
# ip_hash; # 同一 IP 固定到同一台(简单会话保持)
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
4. 检查配置与热重载(高频)
| 命令 | 说明 | 常用示例 |
|---|---|---|
nginx -t | 检查配置文件语法 | 改完配置必跑,报错会指出文件和行号 |
nginx -T | 检查并打印完整配置 | 排查 include 了哪些文件时很有用 |
nginx -s reload | 平滑重载配置 | 不断现有连接,安全应用新配置 |
systemctl reload nginx | 同上(systemd 方式) | — |
nginx -s stop / quit | 快速停止 / 优雅停止 | — |
systemctl status nginx | 查看运行状态 | 启动失败时先看这里 |
nginx -v / -V | 版本 / 编译参数 | -V 可查安装路径和模块 |
标准改配置流程:
vim /etc/nginx/conf.d/myapp.conf # 1. 改配置
nginx -t # 2. 检查语法(必须看到 successful)
nginx -s reload # 3. 平滑重载
5. 日志排查
| 日志 | 默认位置 | 用途 |
|---|---|---|
| 访问日志 access.log | /var/log/nginx/access.log | 每个请求一行:IP、时间、URL、状态码、耗时、UA |
| 错误日志 error.log | /var/log/nginx/error.log | 启动错误、后端连接失败、权限问题 |
# 实时看访问日志
tail -f /var/log/nginx/access.log
# 统计状态码分布(快速判断问题面)
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 找出访问最多的 IP Top10
cut -d' ' -f1 /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# 找所有 5xx 错误
awk '$9 >= 500' /var/log/nginx/access.log | tail -50
# 看最慢的请求(需 log_format 配 $request_time,默认在最后字段)
awk '{print $NF, $7}' /var/log/nginx/access.log | sort -rn | head
自定义日志格式(加请求耗时,写入 http 块):
log_format main '$remote_addr - [$time_local] "$request" '
'$status $body_bytes_sent '
'rt=$request_time uct=$upstream_connect_time urt=$upstream_response_time';
access_log /var/log/nginx/access.log main;
6. Nginx 常见场景解惑
Q:改了配置不生效?
先 nginx -t 看是否报错;再确认改的是被 include 的文件(nginx -T | grep 关键字 验证);最后确认执行的是 reload 而不是只保存了文件。
Q:502 Bad Gateway?
后端服务挂了或没监听对应端口。curl 127.0.0.1:8080 直接测后端;tail /var/log/nginx/error.log 看 connect() failed 详情。
Q:504 Gateway Timeout?
后端响应太慢。查后端日志/慢查询,或临时调大 proxy_read_timeout 300s;。
Q:413 Request Entity Too Large?
上传文件超过限制。在 http 或 server 块加:client_max_body_size 100m;
Q:403 Forbidden?
常见三种原因:目录无权限(nginx 用户读不到)、目录下没有 index 文件且未开 autoindex、被 deny 规则拦截。error.log 会写明具体原因。
7. Nginx 生产实战案例
案例一:大促压测出现大量 499 和 502
背景:大促前压测,QPS 到 3000 后错误率飙升,日志里大量 499(客户端主动断开)和 502。
# 1. 量化错误分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# → 200 正常占多数,499 和 502 各占 5%
# 2. 看错误日志找 502 原因
tail -500 /var/log/nginx/error.log | grep -E "upstream|connect"
# → upstream timed out (110: Connection timed out) while connecting to upstream
# 3. 定位:后端连接数耗尽。查 upstream 是否启用 keepalive
grep -A5 "upstream backend" /etc/nginx/conf.d/*.conf
# → 没有 keepalive 配置,每个请求都新建 TCP 连接,压测下端口耗尽
修复配置:
upstream backend {
server 10.0.1.11:8080;
server 10.0.1.12:8080;
keepalive 64; # 关键:与后端保持长连接池
}
location / {
proxy_pass http://backend;
proxy_http_version 1.1; # 长连接必需
proxy_set_header Connection ""; # 清掉客户端的 Connection 头
}
复测 499/502 归零。要点:高并发下 Nginx 到后端必须开 keepalive,否则 TIME_WAIT 和建连开销会先于应用成为瓶颈。
案例二:全站 HTTPS 迁移
背景:业务要求 HTTP 全量跳转 HTTPS,且不影响老接口的 POST 请求。
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri; # 301 会保留路径和参数
}
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3; # 禁用老旧 TLS1.0/1.1
location / { proxy_pass http://backend; }
}
踩坑记录:老 App 用 301 后 POST 变 GET(部分客户端 301 会改方法)→ 接口改用 308 Permanent Redirect(强制保持原方法)。要点:API 类重定向用 308,网页类用 301。
十一、正则表达式速查
1. 常用元字符
| 类别 | 符号 | 含义 | 示例 |
|---|---|---|---|
| 字符 | . | 任意单个字符(除换行) | a.c 匹配 abc、a1c |
\d \w \s | 数字 / 单词字符 / 空白 | \d{4} 匹配4位数字 | |
\D \W \S | 上面三个的取反 | \S+ 匹配非空白串 | |
| 字符集 | [abc] | a/b/c 任一 | — |
[^abc] | 不是 a/b/c | [^0-9] 非数字 | |
[a-z] [0-9] | 范围 | [a-zA-Z0-9_] 标识符字符 | |
| 量词 | * | 0 次或多次 | ab* 匹配 a、ab、abb |
+ | 1 次或多次 | \d+ 至少一位数字 | |
? | 0 次或 1 次 | colou?r 匹配 color/colour | |
{n} {n,} {n,m} | 指定次数 | \d{3,4} 3到4位数字 | |
| 位置 | ^ | 行首 | ^ERROR 行首的 ERROR |
$ | 行尾 | \.log$ 以 .log 结尾 | |
\b | 单词边界 | \bcat\b 只匹配完整单词 cat | |
| 其他 | ` | ` | 或 |
() | 分组 | (ab)+ 匹配 abab | |
\ | 转义 | \. 匹配真正的点号 |
常用快捷类:
[0-9]=\d、[a-zA-Z0-9_]=\w、[ \t\r\n]=\s。
2. 贪婪与非贪婪
| 模式 | 名称 | 行为 | 示例(文本 <a><b>) |
|---|---|---|---|
<.+> | 贪婪(默认) | 尽量多匹配 | 匹配整个 <a><b> |
<.+?> | 非贪婪(加 ?) | 尽量少匹配 | 只匹配 <a> |
口诀:量词后面加个 ? 就"懒"了,能少匹配就少匹配。
常见用途:从 HTML/JSON 中提取成对标记之间的内容,如 "(.+?)" 提取引号内内容。
注意:grep/sed 默认是 BRE/ERE,不支持
+?这种写法,需用grep -P(PCRE 模式)。awk 同理不支持非贪婪。
3. 分组捕获与反向引用
| 语法 | 说明 | 示例 |
|---|---|---|
(...) | 捕获分组,内容存入编号 | (\d{4})-(\d{2})-(\d{2}) 三个组 |
\1 \2 | 反向引用第 N 组(sed/替换时用) | 见下方 sed 示例 |
(?:...) | 非捕获分组(只分组不编号) | `(?:cat |
$1 $2 | 引用分组(部分工具语法) | awk 的 match 数组、Go/Java 等语言中 |
4. grep 实战示例
# 基础:找 ERROR 或 WARN 开头的行
grep -E '^(ERROR|WARN)' app.log
# 提取 IP 地址(-o 只输出匹配部分)
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' access.log
# 找手机号
grep -oE '1[3-9][0-9]{9}' data.txt
# 找邮箱
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' mail.txt
# 统计每个 IP 出现次数(grep + sort + uniq 经典三件套)
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' access.log | sort | uniq -c | sort -rn | head
# PCRE 模式:支持非贪婪、\d 等(提取引号中的内容)
grep -oP '"name"\s*:\s*"\K[^"]+' data.json
| grep 参数 | 说明 |
|---|---|
-E | 扩展正则(ERE),`+ ? |
-P | Perl 正则(PCRE),支持 \d、非贪婪、断言 |
-o | 只输出匹配的部分(提取神器) |
-v | 反选(不匹配的行) |
-i | 忽略大小写 |
-n | 显示行号 |
-r | 递归目录 |
5. sed 实战示例(分组替换重灾区)
sed 默认 BRE:分组要写
\(...\),引用用\1。加-E后可用(...),与 grep 一致。
# 简单替换:所有 error 改成 ERROR(g = 每行全部替换)
sed -i 's/error/ERROR/g' app.log
# 分组捕获:交换日期格式 2026-07-27 → 27/07/2026
sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/g' date.txt
# 提取:把 "name=tom age=20" 只保留名字
echo 'name=tom age=20' | sed -E 's/name=([a-z]+).*/\1/'
# 输出:tom
# 删除行尾空白(日志清洗常用)
sed -i 's/[ \t]*$//' file.txt
# 删除注释行和空行(处理配置文件)
sed -e '/^#/d' -e '/^$/d' nginx.conf
# 只打印第 10~20 行(sed 当 head/tail 用)
sed -n '10,20p' app.log
# 打印匹配行(-n 抑制默认输出 + p 打印)
sed -n '/ERROR/p' app.log
# 给每行加行号前缀
echo -e 'a\nb\nc' | sed '=' | paste - -
| sed 常用结构 | 说明 |
|---|---|
s/旧/新/ | 替换每行第一个 |
s/旧/新/g | 替换每行所有 |
s/旧/新/2 | 只替换每行第 2 个 |
-i | 直接改文件(-i.bak 先备份再改) |
-n '...p' | 只打印指定内容 |
/模式/d | 删除匹配行 |
6. awk 实战示例
awk 按列处理,正则用于筛选行和切分列。默认按空白分列,
$1第1列、$0整行、NF列数、NR行号。
# 筛选:第 9 列(状态码)是 5xx 的行(~ 表示正则匹配)
awk '$9 ~ /^5/' access.log
# 筛选:第 3 列包含 error(忽略大小写用 tolower)
awk 'tolower($3) ~ /error/' app.log
# 反选:第 1 列不以 192. 开头(!~ 不匹配)
awk '$1 !~ /^192\./' access.log
# 统计:每个 IP 的访问次数(数组用法)
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head
# 求和:统计 GET 请求返回的总字节数
awk '$6 ~ /GET/ {sum += $10} END {print sum" bytes"}' access.log
# 指定分隔符:分析 /etc/passwd(冒号分隔)
awk -F: '$3 >= 1000 {print $1, $3}' /etc/passwd
# 多分隔符:按逗号或分号切
awk -F'[,;]' '{print $2}' data.txt
# 范围提取:打印两个标记之间的行(日志切片神器)
awk '/2026-07-27 10:00/,/2026-07-27 11:00/' app.log
# 格式化输出
awk '{printf "%-15s %6d\n", $1, $2}' data.txt
| awk 内置变量 | 说明 |
|---|---|
$0 $1..$NF | 整行 / 第 N 列 / 最后一列 |
NR | 当前行号(awk 'NR==10' = 第10行) |
NF | 当前行列数 |
FS / -F | 输入分隔符 |
BEGIN{} / END{} | 处理前 / 处理后执行的块 |
7. 正则常见场景解惑
Q:为什么 grep '<<<<<<<' 查 git 冲突标记没问题,但 grep '???' 查问号不行?
? 是元字符,要转义:grep '\?\?\?' 或加 -F 按纯文本匹配:grep -F '???'。只要搜的内容含特殊符号,优先考虑 grep -F。
Q:正则在线验证工具? 改复杂正则前先在线调试:regex101.com(选 PCRE2 或对应语言模式),能实时看到分组和匹配说明。
Q:记住这三个"万金油"模式就够应付 80% 场景
提取引号内容:"([^"]+)"
提取括号内容:\(([^)]+)\)
匹配到行尾:.*$
8. 正则生产实战案例
案例:遭受 CC 攻击,从 8G 访问日志中提取攻击特征并封禁
背景:网站突然变慢,Nginx 连接数打满,怀疑 CC 攻击(大量请求打向同一接口)。
# 1. 找出请求量最大的 IP Top20
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' /var/log/nginx/access.log \
| sort | uniq -c | sort -rn | head -20
# → 前 5 个 IP 每个请求 10 万+,正常用户不可能
# 2. 看这些 IP 在请求什么(确认是攻击不是爬虫)
grep "^1.2.3.4 " /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head
# → 全部密集请求 /api/login,确认 CC 攻击
# 3. 提取攻击 IP 清单(请求超 1 万的)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn \
| awk '$1 > 10000 {print $2}' > /tmp/attack_ips.txt
wc -l /tmp/attack_ips.txt
# 4. 批量封禁
cat /tmp/attack_ips.txt | while read ip; do
firewall-cmd --add-rich-rule="rule family=ipv4 source address=$ip drop"
done
# 5. 验证恢复
ss -s # 连接数回落
tail -f /var/log/nginx/access.log # 流量正常化
要点:grep 提取 → sort|uniq -c 统计 → awk 阈值过滤 → 批量执行,这套组合拳是所有日志应急分析的万能模板。事后把限流(limit_req_zone)加进 Nginx 配置防止复发。
十二、网络设备常用命令
覆盖华为(VRP)、华三 H3C(Comware)、思科(IOS)交换机及华为防火墙(USG)。三大厂商命令体系对比见第 6 节对照表。
1. 各厂商模式结构(入门先懂这个)
| 厂商 | 用户视图 | 特权/系统视图 | 退出/返回 | 撤销命令 |
|---|---|---|---|---|
| 华为 | <Huawei> | system-view → [Huawei] | quit 逐级退 / return 回用户视图 | undo xxx |
| 华三 | <H3C> | system-view → [H3C] | quit / return | undo xxx |
| 思科 | Switch> | enable → Switch#,configure terminal → Switch(config)# | exit / end 回特权 | no xxx |
记忆点:华为、华三命令几乎同源(
display+undo),思科自成一派(show+no)。所有设备都支持 Tab 补全 和 ? 查看可用命令(思科需先在用户视图terminal editing)。
2. 华为交换机(VRP)常用命令
查看类(display,日常排障主力):
| 命令 | 说明 |
|---|---|
display current-configuration | 当前运行配置(可接 ` |
display saved-configuration | 已保存的配置(开机加载的那份) |
display interface brief | 所有接口状态一览(up/down、速率、VLAN) |
display interface GigabitEthernet 0/0/1 | 单接口详情(错包、流量统计) |
display vlan | 所有 VLAN 及成员端口 |
display mac-address | MAC 地址表(定位设备接在哪个口) |
display arp | ARP 表(IP 与 MAC 对应关系) |
display ip routing-table | 路由表 |
display eth-trunk 1 | 链路聚合状态 |
display stp brief | 生成树状态(查环路、根桥) |
display lldp neighbor brief | LLDP 邻居(看对端接的什么设备) |
display cpu-usage / display memory-usage | CPU / 内存占用 |
display temperature all | 各板卡温度 |
display device / display power / display fan | 硬件状态(电源、风扇) |
display interface transceiver verbose | 光模块收发光功率(排查光衰) |
display logbuffer | 日志缓冲(先看最近的告警) |
display alarm active | 当前活动告警 |
display version / display device manuinfo | 版本 / 序列号 |
配置类(system-view 下):
# 基础
system-view # 进入系统视图
sysname Core-SW01 # 设备命名
# VLAN
vlan batch 10 20 30 # 批量创建 VLAN
vlan 10
description Office # 给 VLAN 加描述
# 接口配置(access 口接终端)
interface GigabitEthernet 0/0/1
description PC-zhangsan # 接口描述(强烈建议养成习惯)
port link-type access
port default vlan 10
# 接口配置(trunk 口接交换机/AP)
interface GigabitEthernet 0/0/24
port link-type trunk
port trunk allow-pass vlan 10 20 30
# 三层接口(VLAN 网关)
interface Vlanif 10
ip address 192.168.10.1 24
# 链路聚合(两个物理口绑成一个逻辑口)
interface Eth-Trunk 1
port link-type trunk
port trunk allow-pass vlan 10 20
interface GigabitEthernet 0/0/1
eth-trunk 1
interface GigabitEthernet 0/0/2
eth-trunk 1
# 静态路由
ip route-static 0.0.0.0 0.0.0.0 192.168.10.254
# 保存配置(不做这步重启全丢!)
save # 用户视图下执行,输 y 确认
维护类:
| 命令 | 说明 |
|---|---|
reset counters interface | 清空接口计数(观察错包增长前清零) |
shutdown / undo shutdown | 关闭 / 开启接口(接口视图下) |
reboot | 重启设备 |
startup saved-configuration xxx.cfg | 指定下次启动加载的配置文件 |
dir / delete / tftp ... put/get | 文件系统操作(备份配置到 TFTP) |
3. 华三 H3C 交换机(Comware)常用命令
与华为高度相似,以下为差异点,未列出的命令基本与华为一致(display 系通用)。
| 操作 | 华三命令 | 与华为的差异 |
|---|---|---|
| access 口划入 VLAN | port access vlan 10 | 华为是 port default vlan 10 |
| trunk 放行 VLAN | port trunk permit vlan 10 20 | 华为是 allow-pass |
| 链路聚合 | interface Bridge-Aggregation 1(BAGG) | 华为是 Eth-Trunk |
| 成员口加入聚合 | port link-aggregation group 1 | 华为是 eth-trunk 1 |
| 保存配置 | save force | 华为 save 后交互确认 |
| 查看光功率 | display transceiver diagnosis interface Ten-GigabitEthernet 1/0/25 | 命令名不同 |
| 查看序列号 | display device manuinfo | 一致 |
| 批量端口视图 | interface range GigabitEthernet 1/0/1 to GigabitEthernet 1/0/10 | 华为用 port-group |
# 华三完整配置示例(Comware V7)
system-view
sysname Access-SW01
vlan 10
interface GigabitEthernet 1/0/1
port link-type access
port access vlan 10
interface GigabitEthernet 1/0/24
port link-type trunk
port trunk permit vlan 10 20
save force
4. 思科交换机(IOS)常用命令
查看类(show):
| 命令 | 说明 |
|---|---|
show running-config | 当前配置(可接 | include 关键字,管道竖线前需空格或转义) |
show startup-config | 启动配置 |
show ip interface brief | 接口 IP/状态一览(最常用) |
show interfaces status | 接口速率、双工、VLAN 一览 |
show interfaces gi1/0/1 | 单接口详情(错包计数) |
show vlan brief | VLAN 及成员端口 |
show mac address-table | MAC 地址表 |
show arp | ARP 表 |
show ip route | 路由表 |
show etherchannel summary | 聚合状态 |
show spanning-tree | 生成树(查阻塞口、根桥) |
show cdp neighbors detail / show lldp neighbors | 邻居设备信息 |
show processes cpu / show processes memory | CPU / 内存 |
show logging | 日志 |
show version | 版本、序列号、运行时长 |
show interfaces transceiver | 光模块功率(部分型号) |
show errdisable recovery | 被 errdisable 关闭的端口 |
配置类:
enable # 进入特权模式
configure terminal # 进入全局配置
hostname Core-SW01
# VLAN
vlan 10
name Office
# access 口
interface GigabitEthernet1/0/1
description PC-zhangsan
switchport mode access
switchport access vlan 10
spanning-tree portfast # 接终端的口跳过 STP 等待,加快上线
# trunk 口
interface GigabitEthernet1/0/24
switchport trunk encapsulation dot1q # 老型号需先指定封装
switchport mode trunk
switchport trunk allowed vlan 10,20,30
# 批量配置接口(range 是思科一大便利)
interface range GigabitEthernet1/0/1 - 10
switchport mode access
switchport access vlan 10
# 三层接口
interface Vlan 10
ip address 192.168.10.1 255.255.255.0
no shutdown
ip routing # 开启三层转发(三层交换机必开)
# 链路聚合
interface Port-channel 1
switchport mode trunk
interface GigabitEthernet1/0/1
channel-group 1 mode active
interface GigabitEthernet1/0/2
channel-group 1 mode active
# 默认路由
ip route 0.0.0.0 0.0.0.0 192.168.10.254
# 保存(特权模式下,相当于华为的 save)
write memory
# 或
copy running-config startup-config
5. 华为防火墙(USG 系列)常用命令
防火墙逻辑与交换机不同,核心概念:安全区域(Zone)→ 接口加入区域 → 安全策略控制区域间流量。
| 命令 | 说明 |
|---|---|
display zone | 查看安全区域及成员接口 |
display ip interface brief | 接口状态 |
display security-policy rule all | 查看所有安全策略 |
display firewall session table | 查看会话表(排障核心:有去有回才算通) |
display nat-policy rule all | 查看 NAT 策略 |
display ip routing-table | 路由表 |
display firewall defend flag | 攻击防范开关状态 |
# 基础组网配置示例
system-view
# 1. 接口配 IP 并加入安全区域
interface GigabitEthernet 1/0/1 # 接内网
ip address 192.168.1.1 24
interface GigabitEthernet 1/0/2 # 接外网
ip address 202.100.1.2 30
firewall zone trust
add interface GigabitEthernet 1/0/1
firewall zone untrust
add interface GigabitEthernet 1/0/2
# 2. 安全策略:允许内网访问外网
security-policy
rule name trust_to_untrust
source-zone trust
destination-zone untrust
source-address 192.168.1.0 24
action permit
# 3. NAT:内网地址转换为出口公网 IP
nat-policy
rule name nat_out
source-zone trust
destination-zone untrust
source-address 192.168.1.0 24
action source-nat easy-ip # easy-ip = 借用出接口地址
# 4. 默认路由指向运营商
ip route-static 0.0.0.0 0.0.0.0 202.100.1.1
save
防火墙排障三板斧:
# 1. 看会话有没有建立(源IP+目的IP过滤)
display firewall session table source inside 192.168.1.100
# 2. 看策略是否命中(命中数 hit 为 0 说明流量没匹配到这条策略)
display security-policy rule name trust_to_untrust
# 3. 会话、策略都没问题 → 查路由和 NAT
display ip routing-table 202.100.1.0
display nat-policy rule all
6. 三大厂商命令对照表
| 功能 | 华为 | 华三 H3C | 思科 |
|---|---|---|---|
| 查看当前配置 | display current-configuration | 同华为 | show running-config |
| 保存配置 | save | save force | write memory |
| 进入配置模式 | system-view | system-view | enable + configure terminal |
| 撤销配置 | undo xxx | undo xxx | no xxx |
| 接口状态一览 | display interface brief | 同华为 | show ip interface brief |
| 查看 VLAN | display vlan | 同华为 | show vlan brief |
| 查看 MAC 表 | display mac-address | 同华为 | show mac address-table |
| 查看 ARP | display arp | 同华为 | show arp |
| 查看路由 | display ip routing-table | 同华为 | show ip route |
| access 口划 VLAN | port default vlan 10 | port access vlan 10 | switchport access vlan 10 |
| trunk 放行 VLAN | port trunk allow-pass vlan 10 | port trunk permit vlan 10 | switchport trunk allowed vlan 10 |
| 链路聚合 | Eth-Trunk | Bridge-Aggregation | Port-channel |
| 查邻居 | display lldp neighbor brief | 同华为 | show cdp/lldp neighbors |
| 查光功率 | display interface transceiver verbose | display transceiver diagnosis | show interfaces transceiver |
| 查日志 | display logbuffer | 同华为 | show logging |
| 清空接口计数 | reset counters interface | 同华为 | clear counters |
| 批量接口 | port-group | interface range ... to ... | interface range gi1/0/1 - 10 |
| 过滤输出 | | include 关键字 | 同华为 | | include 关键字 |
7. 网络设备常见场景解惑
Q:知道一个 IP,怎么找到它接在交换机哪个端口? 三步定位法(核心排障技能):
# 第一步:在网关设备上查 ARP,拿到 MAC(华为为例)
display arp | include 192.168.1.100
# 第二步:在接入交换机上查 MAC 表,找到端口
display mac-address | include xxxx-xxxx-xxxx
# 第三步:如果端口是 trunk 接了下级交换机,用 LLDP 找到下级设备,重复第二步
display lldp neighbor brief
# 思科对应命令:show arp | include → show mac address-table | include → show cdp neighbors
Q:终端上不了网,交换机侧怎么排查?
1. display interface brief # 端口是不是 up?down 则查网线/模块
2. display interface gi0/0/1 # 有没有大量 CRC/错包?有则换线或查光衰
3. display mac-address # 端口有没有学到终端 MAC?没学到查 VLAN 配置
4. display vlan # 端口划的 VLAN 对不对
5. display stp brief # 端口是不是被生成树阻塞(discarding)
Q:网络时断时续/大面积卡顿,怀疑环路?
display mac-address flapping record # 华为:MAC 漂移记录,同一 MAC 在多个端口间跳 = 环路
display stp brief # 看是否有端口频繁拓扑变化
# 临时止血:shutdown 掉可疑端口;根治:启用 STP 并配置边缘端口
# 思科:show mac address-table 看同一 MAC 是否出现在多个 access 口
Q:光模块链路不稳定怎么确认?
# 华为:查看收发光功率(单位 dBm)
display interface transceiver verbose
# 接收功率(Rx Power)低于阈值下限(如 -14dBm 以下)说明光衰过大:查跳纤、法兰头、弯折
# 华三:display transceiver diagnosis interface ...
Q:配置备份与恢复怎么做?
# 华为/华三:备份到 TFTP 服务器
tftp 192.168.1.200 put vrpcfg.zip
# 恢复:下载后指定为启动配置并重启
tftp 192.168.1.200 get vrpcfg.zip
startup saved-configuration vrpcfg.zip
reboot
# 思科
copy running-config tftp://192.168.1.200/sw01-config
copy tftp://192.168.1.200/sw01-config startup-config
reload
Q:改配置怕改挂,怎么留后路?
# 方法一:改之前先保存,改挂了重启恢复(配置未 save 重启即还原)
# 方法二:华为/华三定时重启兜底
schedule reboot at 02:00 # 改挂了就等它重启回旧配置,改成功了再取消
undo schedule reboot
# 思科:reload in 10(10分钟后自动重启),改成功后 reload cancel
8. 网络设备生产实战案例
案例一:某楼层突然断网,逐跳定位到接入交换机光模块
背景:3 楼整层办公网不通,其他楼层正常。
# 1. 核心交换机看汇聚链路状态(华为)
display interface brief | include down
# → GE1/0/8(下联 3 楼汇聚)物理 down
# 2. 看该口光功率
display interface transceiver interface GE1/0/8 verbose
# → Rx Power: -30.2 dBm(低于阈值下限 -14dBm,收不到光)
# 3. 判定:不是配置问题,是物理链路。联系现场查 3 楼机房:
# 发现保洁碰到光纤跳线,接头松动,重新插拔后 Rx 恢复 -8.5dBm,链路 up
# 4. 验证终端恢复
display mac-address interface GE1/0/8 | count # MAC 数回升
要点:整区域断网先看汇聚口物理状态,再看光功率,物理层问题占比远超配置问题。收光低于 -14dBm 基本可判定光路故障。
案例二:远程割接改错路由,reload in 10 捡回一命
背景:深夜远程割接,给分公司思科路由器加静态路由,敲错下一跳导致隧道中断、设备失联。
# 事前有准备(割接标准动作):
reload in 10 # 10 分钟后自动重启,改挂了自动回滚(配置未 write)
configure terminal
ip route 10.3.0.0 255.255.255.0 192.168.255.2 # ← 下一跳敲错
# 结果:路由生效瞬间链路中断,SSH 断开,无法远程恢复
# 但 10 分钟后设备自动 reload,启动加载的是改之前的 startup-config,链路自愈
# 重新连上后:
ping 10.3.0.1 # 先验证下一跳可达,再谨慎配置
write memory # 确认无误才保存,然后 reload cancel
要点:远程操作网络设备,不先挂 reload 兜底等于裸奔。配置未 write 前重启即还原,这是网络工程师最重要的保险绳。
十三、网络设备堆叠配置
堆叠 = 多台物理交换机虚拟成一台逻辑设备:统一 IP 管理、跨设备链路聚合、主备自动切换。各厂商技术名称:华为 iStack(盒式)/ CSS(框式)、华三 IRF、思科 StackWise(盒式)/ VSS(框式)。
1. 堆叠基础概念
| 概念 | 说明 |
|---|---|
| 堆叠角色 | 主用(Master/Active):管理整个堆叠;备用(Standby):主的备胎;从(Slave/Member):普通成员 |
| 选举依据 | 优先级高优先 → 运行时间长优先 → MAC 地址小优先(想让谁当主,就把谁的优先级调大) |
| 成员编号 | 每台成员有唯一 ID(华为 slot 号、华三 member 号、思科 switch 号),编号冲突会无法加入 |
| 堆叠口 | 专用堆叠卡线缆,或用业务口承担(业务口堆叠),用于成员间同步数据和心跳 |
| 堆叠后接口编号 | 会带上成员号,如华为 GE0/0/1 变为 GE1/0/1、GE2/0/1;思科 gi1/0/1 → gi2/0/1 |
2. 华为 iStack 配置(S 系列盒式)
支持两种堆叠方式: 堆叠卡堆叠(插上堆叠卡+专用线缆即可,推荐)和业务口堆叠(用普通光/电口当堆叠口,灵活但占用业务口)。
# ======== 第一台(计划当主设备)========
system-view
sysname Stack-SW
stack slot 0 priority 200 # 优先级默认 100,调大确保它当主
# 业务口堆叠方式:把 23/24 口加入堆叠口 0/1
interface stack-port 0/1
port interface GigabitEthernet 0/0/23 enable
port interface GigabitEthernet 0/0/24 enable
quit
save # 保存
# ======== 第二台(成员)========
system-view
stack slot 0 renumber 1 # 改成员编号为 1(默认 0,不改会冲突!)
stack slot 1 priority 100
interface stack-port 1/2 # 与第一台交叉对应:0/1 ↔ 1/2
port interface GigabitEthernet 0/0/23 enable
port interface GigabitEthernet 0/0/24 enable
quit
save
# ======== 两台都接好线后重启,堆叠自动建立 ========
reboot
堆叠卡堆叠方式(如 S5720LI、S5730 配 ES5D21VST000 堆叠卡):只需插卡接线,上电自动组成堆叠,再按需调优先级和编号即可。
查看与维护:
| 命令 | 说明 |
|---|---|
display stack | 堆叠整体状态:成员、角色、优先级、MAC |
display stack topology | 拓扑结构(环形/链形) |
display stack port | 堆叠口状态(up/down) |
display stack peers | 各成员堆叠口连接关系 |
display stack configuration | 堆叠相关配置 |
display stack link | 链路详细状态 |
框式 CSS(S7700/S9700/S12700)简要:
# 两台框式集群(CSS 卡方式)
set css mode css-card
set css id 1 # 另一台设为 2
set css priority 200 # 另一台保持默认
save
css enable # 使能后重启生效,两台组成集群
# 查看:display css status / display css channel
3. 华三 IRF 配置
IRF 是华三王牌技术,盒式、框式通用,最大支持 4~10 台(按型号)。配置顺序很关键:先改编号重启,再连堆叠线。
# ======== 第一台(主设备,member 1)========
system-view
irf member 1 priority 32 # 优先级 1~32,调满确保当主
# 创建 IRF 端口并绑定物理口(用最后两个万兆口)
irf-port 1/1
port group interface Ten-GigabitEthernet 1/0/49
port group interface Ten-GigabitEthernet 1/0/50
quit
save force
# 不重启,先配第二台
# ======== 第二台(member 2)========
system-view
irf member 1 renumber 2 # 改成员编号,**必须 save + reboot 才生效**
save force
reboot
# 重启后接口编号已从 1/0/x 变为 2/0/x,继续配置:
system-view
irf-port 2/2 # 与第一台交叉:1/1 ↔ 2/2
port group interface Ten-GigabitEthernet 2/0/49
port group interface Ten-GigabitEthernet 2/0/50
quit
save force
# ======== 两台都接好堆叠线,在各自设备上激活 ========
irf-port-configuration active # 激活 IRF,设备自动协商建堆叠,备机会重启
MAD 检测(多 Active 检测,防脑裂,生产环境必配):
# BFD MAD 方式(用一对独立网口直连做检测链路)
vlan 999
interface GigabitEthernet 1/0/24 # 成员1的检测口
port link-type access
port access vlan 999
interface GigabitEthernet 2/0/24 # 成员2的检测口(两台直连)
port link-type access
port access vlan 999
interface Vlan-interface 999
mad bfd enable
mad ip address 192.168.255.1 255.255.255.252 member 1
mad ip address 192.168.255.2 255.255.255.252 member 2
# 注意:开启 MAD 的 VLAN 接口不能再配普通 IP 业务
查看与维护:
| 命令 | 说明 |
|---|---|
display irf | IRF 总览:成员、角色、优先级 |
display irf topology | 拓扑(环形/链形)及链路状态 |
display irf link | 各成员 IRF 口连接详情 |
display irf configuration | IRF 配置 |
display mad verbose | MAD 检测状态 |
irf switch-to member 2 | 切换到指定成员操作(类似远程登录成员) |
4. 思科 StackWise 配置(Catalyst 盒式)
思科盒式堆叠(3750/3850/9300 等)最大特点是几乎免配置:用专用堆叠线缆把成员环形连接,上电自动选举建堆叠。
# 基本零配置:接好堆叠线(Switch1的stack1→Switch2的stack2,Switch2的stack1→Switch1的stack2,组成环)
# 上电后自动选举主设备(Active),其余为 Standby/Member
# 想让某台稳定当主:调大优先级(1~15,默认 1)
switch 1 priority 15 # 改完重启生效
# 修改成员编号(出厂默认都是 1,新设备加入前检查)
switch 2 renumber 3 # 改完需 save + reload
write memory
reload
9300 系列(StackWise-480/1T) 同样即插即用,数据堆叠口支持带宽更高,还支持 StackWise Virtual(两台 9400/9500/9600 跨机箱虚拟化,类似 VSS,需配 stackwise-virtual + domain + 双活检测)。
查看与维护:
| 命令 | 说明 |
|---|---|
show switch | 成员列表:编号、角色、优先级、MAC、状态 |
show switch detail | 含堆叠口状态的详细信息 |
show switch stack-ports | 各成员堆叠口 up/down |
show switch neighbors | 堆叠邻居关系 |
show platform stack-manager | 堆叠管理器状态(排障深入用) |
show redundancy | 主备冗余状态 |
request platform software package | 9300 系列整体升级 |
框式 VSS(Catalyst 6500/4500)简要:
# 两台框式虚拟化为一台
switch virtual domain 10
switch 1 # 另一台为 switch 2
switch 1 priority 110
# VSL 链路(虚拟交换链路,至少绑 2 个万兆口)
interface port-channel 10
switch virtual link 1
interface TenGigabitEthernet 1/1/1
channel-group 10 mode on
# 转换模式(会重启生效)
switch convert mode virtual
# 双活检测必配:show switch virtual / show switch virtual link
5. 三家堆叠技术对照表
| 项目 | 华为 | 华三 H3C | 思科 |
|---|---|---|---|
| 盒式技术名 | iStack | IRF | StackWise |
| 框式技术名 | CSS | IRF | VSS / StackWise Virtual |
| 典型成员上限 | 9 台(按型号) | 4~10 台(按型号) | 8~9 台(按系列) |
| 选举依据 | 优先级→运行时长→MAC | 优先级→运行时长→MAC | 优先级→MAC |
| 优先级默认值/范围 | 100(1~255) | 1(1~32) | 1(1~15) |
| 配置复杂度 | 中(业务口堆叠需配置) | 较高(编号/端口/激活分步) | 低(即插即用) |
| 脑裂防护 | MAD(mad detect) | BFD/LACP/ARP MAD | StackWise 线缆机制 + PAgP/fast-hello |
| 加入新成员 | 改编号+接线+重启 | renumber→reboot→绑口→active | 接线即入(版本需一致) |
| 查看主命令 | display stack | display irf | show switch |
6. 堆叠使用注意事项(重要)
规划与实施前:
- 版本必须一致:所有成员的软件版本、型号(多数要求同系列)需一致,版本不一致的成员会被拒绝加入或反复重启。新设备入堆前单独升级好版本。
- 成员编号先规划:出厂默认编号都一样(华为/思科默认 1、华三默认 1),先单机改好编号再连堆叠线,否则后上的设备会被迫重启改号。
- 环形连接优于链形:堆叠线缆首尾相连组成环(如 A→B→C→A),任何一根线断开堆叠都不分裂;链形连接中间断一根就一分为二。
- 堆叠口带宽要够:成员间同步所有表项和流量(跨成员转发也走堆叠口),业务口堆叠时至少绑 2 个万兆口,且这些口不能再跑业务。
运行与维护:
- 必须配置分裂检测(MAD/双活检测):堆叠线全断时两台成员都会认为自己是主(脑裂),同 IP 同 MAC 的设备并存会冲垮全网。MAD 检测到分裂后会把多余成员的所有业务口关闭,只留一台工作。
- 接入层设备跨成员聚合:服务器/下联交换机双上行时,两条链路分别接不同成员并配跨设备聚合(Eth-Trunk/BAGG/Port-channel),这样单台成员故障业务不中断——这才是堆叠最大的价值。
- 堆叠后接口编号整体变化:堆叠前写好的脚本、监控、配置基线里的接口名(如
GE0/0/1)要批量更新为带成员号的形式(GE1/0/1)。 - 升级要整体规划:堆叠系统一升级就是所有成员重启,业务窗口要留足。跨成员聚合 + 逐台重启(ISSU/平滑升级需型号支持)可减少中断。
- 主设备故障切换时间:主挂掉后备机接管,通常秒级收敛;期间管理面(telnet/ssh)会短暂中断,转发面靠跨成员聚合保障不断流。
- 堆叠线缆是专用耗材:长度有限(常见 0.5m/1m/3m/5m),只适用于同机柜或相邻机柜,禁止跨楼层/跨机房堆叠;长距离场景改用 M-LAG(华为)/ vPC(思科数据中心)。
容易踩的坑:
- 华三改
renumber后必须 save 并 reboot 才生效,且旧配置里的接口名全部失效——改号前先display this备份配置文本,改号后按新接口名重配。 - 思科新成员加入会自动同步主设备配置和 IOS 版本(自动升级/降级),版本差异大时会反复重启,入堆前最好先手动对齐版本。
- 华为业务口堆叠的物理口被
port interface ... enable后,该口原有业务配置会丢失且不能再配业务。 - 堆叠分裂恢复后,被 MAD 关掉的端口需要手动恢复(华三
mad restore,华为重启或undo mad视版本)或重启设备。
7. 堆叠常见场景解惑
Q:怎么确认堆叠选举结果是否符合预期?
# 华为
display stack # 看 Role:Master/Standby/Slave 和 Priority
# 华三
display irf # 看 Role:Master/Slave
# 思科
show switch # 看 Role:Active/Standby/Member
# 不符合预期:调高目标设备优先级并重启(选举是抢占式的,优先级高的重启后夺主)
Q:堆叠分裂(脑裂)了怎么发现和恢复?
# 现象:网络中同一管理 IP 时通时断、MAC 表震荡、日志报 duplicate address
# 华三确认:display mad verbose(显示 Detected 状态)
# 恢复:先修复堆叠线缆 → 被 MAD 关闭端口的成员执行 mad restore 或重启该成员
# 预防:堆叠口至少 2 条物理链路 + 环形连接 + 配置 MAD,三线并进
Q:如何在线增加一台新成员?
# 通用步骤:
1. 新设备单独上电,升级/降级到与堆叠系统完全一致的版本
2. 配置为不冲突的成员编号(如现有 1、2,新设备设为 3)
3. 配置堆叠口(业务口堆叠方式需要;堆叠卡方式跳过)
4. 接好堆叠线(先接一环,设备加入后再闭合整个环,避免拓扑震荡)
5. display stack / display irf / show switch 确认 Ready/正常加入
Q:堆叠设备怎么做版本升级?
# 传统方式(有中断):上传新固件 → 所有成员指定启动文件 → 整体 reboot
# 华为:startup system-software xxx.cc all
# 华三:boot-loader file xxx.ipe all slot
# 思科 3750:archive download-sw tftp://...(自动分发到所有成员)
# 思科 9300:request platform software package install file ...
# 低中断方式:查型号是否支持 ISSU(思科)/ 智能升级(华为 S 系列部分支持逐台升级)
Q:堆叠 vs M-LAG/vPC 怎么选?
| 维度 | 堆叠(iStack/IRF/StackWise) | M-LAG / vPC |
|---|---|---|
| 管理面 | 一台设备,配置一份 | 两台独立设备,各配各的 |
| 升级中断 | 整体重启,中断风险大 | 逐台升级,业务无感知 |
| 控制面 | 单一控制面(主控挂了靠备接管) | 双控制面,互为主备更可靠 |
| 适用场景 | 接入层、同机柜、追求简单 | 核心/汇聚、数据中心、要求高可用 |
| 距离限制 | 同机柜(堆叠线长度) | 可跨机房(peer-link 用光纤) |
经验法则:接入层用堆叠图省事,核心/汇聚用 M-LAG 保平安。
8. 堆叠生产实战案例
案例:机房整理线缆碰掉堆叠线,脑裂导致全网震荡
背景:周末机房整理线缆,两台堆叠成员的堆叠线被同时碰松,接入层大面积丢包 3 分钟。
# 事故经过还原(事后查日志):
1. 堆叠线断开 → 两台成员各自认为对方死了,都升为主(脑裂)
2. 两台相同 IP/MAC 的设备同时在线 → 核心交换机 MAC 表疯狂震荡
display mac-address flapping record # 几十条漂移记录
3. 幸亏配置了 BFD MAD:检测到多 Active 后,成员 2 自动关闭所有业务口
display mad verbose # Current status: Detected
4. 接入层只剩成员 1 工作,业务自动恢复(但容量减半)
# 恢复过程:
1. 重新插紧堆叠线,确认链路恢复
display irf topology # 链路状态 UP
2. 恢复被 MAD 关闭的端口
mad restore # 成员 2 端口重新启用(或重启该成员)
3. 验证
display irf # 两台成员,一主一备,状态正常
display interface brief | include down # 无异常 down 口
# 整改措施:
- 堆叠线换带卡扣的专用线缆并打标签“禁止触碰”
- 堆叠口从 2 条增加到 4 条链路(两根同时断的概率趋近于零)
- 机房施工规定:涉及堆叠区域必须由网络工程师陪同
要点:这次事故中 MAD 是真正的救命者——没有 MAD,两台同 IP 设备互掐会造成全网 ARP 混乱,恢复时间从 3 分钟变成不可控。同时也验证了“环形连接”的必要性:链形拓扑单点断链即分裂。
十四、SSH 与网络排障
1. SSH 登录与密钥配置
| 命令 | 说明 | 常用示例 |
|---|---|---|
ssh | 远程登录 | ssh user@host、ssh -p 2222 user@host(非标端口) |
ssh-keygen | 生成密钥对 | ssh-keygen -t ed25519(推荐)或 ssh-keygen -t rsa -b 4096 |
ssh-copy-id | 公钥推送到服务器(免密登录) | ssh-copy-id user@host |
ssh-add | 把私钥加入 agent | 免输私钥密码 |
免密登录手工配置(ssh-copy-id 不可用时):
# 1. 本地生成密钥(一路回车)
ssh-keygen -t ed25519
# 2. 公钥内容追加到服务器的 ~/.ssh/authorized_keys
cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
# 3. 服务器侧权限必须正确(否则免密失败,常见坑!)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
~/.ssh/config 配置别名与跳板机(高频提效):
# 登录只需 ssh prod-web,不用记 IP 和端口
Host prod-web
HostName 192.168.10.11
Port 2222
User ops
# 通过跳板机访问内网机器(ssh 内置 ProxyJump)
Host inner-db
HostName 10.0.1.20
User dba
ProxyJump jump-server # 先连跳板机再连目标
Host jump-server
HostName 120.27.x.x
User ops
2. SSH 端口转发(三种隧道)
| 参数 | 名称 | 作用 | 典型场景 |
|---|---|---|---|
-L | 本地转发 | 本地端口 → 通过 SSH 服务器 → 目标 | 本地访问远端内网服务 |
-R | 远程转发 | 远端端口 → 通过 SSH 连回 → 本地服务 | 内网服务暴露给外网(内网穿透) |
-D | 动态转发 | 本地 SOCKS5 代理 | 浏览器走代理访问内网全部资源 |
# -L 本地转发:访问本地 13306 等于访问远端内网的 MySQL
ssh -L 13306:10.0.1.20:3306 user@jump-server -N
# -N 不执行远程命令(只建隧道),可加 -f 放后台
# -R 远程转发:把本地的 8080 服务暴露到公网服务器的 18080
ssh -R 18080:localhost:8080 user@public-server -N
# -D 动态转发:本地 1080 变 SOCKS5 代理,浏览器配上即可访问整个内网
ssh -D 1080 user@jump-server -N
3. scp 与 rsync 文件传输
| 命令 | 说明 | 常用示例 |
|---|---|---|
scp | 简单拷贝 | scp file user@host:/path/、scp -r dir user@host:/path/ |
rsync | 增量同步(推荐) | 断点续传、只传差异,大目录/备份首选 |
rsync 高频用法:
# 本地目录同步到远端(最常用组合 -avz)
rsync -avz ./dist/ user@host:/var/www/html/
# -a 归档(保留权限/时间/软链) -v 显示过程 -z 压缩传输
# 注意末尾斜杠:dist/ 同步内容,dist 同步目录本身
# 断点续传大文件(-P = --partial --progress)
rsync -avzP bigfile.iso user@host:/data/
# 删除目标多余文件(完全镜像,危险但有用)
rsync -avz --delete ./dist/ user@host:/var/www/html/
# 排除文件/限速/指定 SSH 端口
rsync -avz --exclude='*.log' --exclude='.git' --bwlimit=10000 -e 'ssh -p 2222' ./src/ user@host:/backup/
# 拉取远端到本地(方向反过来)
rsync -avz user@host:/var/log/nginx/ ./logs/
4. tcpdump 抓包(网络问题终审法官)
| 场景 | 命令 |
|---|---|
| 抓某主机流量 | tcpdump -i any host 192.168.1.10 |
| 抓某端口 | tcpdump -i any port 3306 |
| 组合条件 | tcpdump -i any host 10.0.1.5 and port 80 |
| 保存到文件(Wireshark 分析) | tcpdump -i any -w /tmp/cap.pcap host x and port y |
| 看内容(ASCII) | tcpdump -i any -A port 80 |
| 只看握手包(排查连不上) | `tcpdump -i any ’tcp[tcpflags] & (tcp-syn |
# 常用参数:
# -i any 所有网卡(生产抓包常用,避免选错网卡)
# -nn 不解析域名/服务名(显示纯 IP 端口,更快更准)
# -c 100 抓够 100 个包自动停
# -s 0 抓完整包(默认可能截断)
# 实战组合:抓 3306 端口的前 200 个包存文件
tcpdump -i any -nn -c 200 -s 0 -w /tmp/mysql.pcap port 3306
5. nmap 端口扫描
| 命令 | 说明 |
|---|---|
nmap 192.168.1.10 | 扫主机常用 1000 端口 |
nmap -p 80,443,3306 192.168.1.10 | 指定端口 |
nmap -p 1-65535 192.168.1.10 | 全端口扫 |
nmap -sV 192.168.1.10 | 探测服务版本 |
nmap -sn 192.168.1.0/24 | ping 扫网段(找在线主机) |
nmap -O 192.168.1.10 | 探测操作系统 |
6. dig 与 DNS 排查
| 命令 | 说明 |
|---|---|
dig baidu.com | 基本查询(看 ANSWER SECTION) |
dig @8.8.8.8 baidu.com | 指定 DNS 服务器(对比排查 DNS 污染/不一致) |
dig baidu.com +short | 只输出结果 IP(脚本里用) |
dig baidu.com ANY / MX / CNAME / TXT | 查指定记录类型 |
dig -x 8.8.8.8 | 反向解析(IP 查域名) |
dig +trace baidu.com | 从根服务器逐级追踪解析过程 |
nslookup baidu.com | 简单查询(Windows/Linux 通用) |
7. mtr 路由诊断
mtr baidu.com # ping + traceroute 合体,持续统计每跳丢包率
mtr -rwbzc 100 baidu.com # 报告模式:100 个包后输出汇总
# 看 Loss% 列:某一跳开始持续丢包 = 该节点或其后链路问题
8. 生产实战案例
案例一:通过 SSH 隧道紧急排查生产数据库
背景:生产 MySQL 只允许应用服务器访问,本地 Navicat 连不上,急需查一条脏数据。
# 1. 建立隧道:本地 13306 → 跳板机 → 内网 DB 的 3306
ssh -L 13306:10.0.1.20:3306 ops@jump-server -N -f
# 2. 本地客户端连接 127.0.0.1:13306 即可,流量全部走加密隧道
mysql -h 127.0.0.1 -P 13306 -u dba -p
# 3. 用完关隧道
kill $(lsof -ti:13306)
要点:不开防火墙、不改数据库绑定地址,零侵入完成排查。
案例二:接口间歇性超时,抓包定位是网络还是应用
背景:调用方反馈接口偶发超时 3 秒,应用日志却显示处理只要 50ms,两边扯皮。
# 在服务端抓包,重点看握手和响应时间差
tcpdump -i any -nn -w /tmp/api.pcap port 8080
# 复现一次后停止,用 Wireshark 打开分析
结论分析:
- 若 SYN 发出后很久才收到 SYN-ACK → 网络/负载均衡问题
- 若握手很快,但 HTTP 请求到响应间隔大 → 应用或上游依赖问题
- 若有大量 重传包(Retransmission) → 链路丢包,查交换机/网卡
本案例最终发现是 LB 到后端节点偶发丢包,更换故障网卡解决。
案例三:用 rsync 做零停机数据迁移
背景:旧服务器 200G 静态资源迁移到新机器,要求停机时间最短。
# 1. 第一次全量同步(业务不停机,跑着同步)
rsync -avz /data/uploads/ new-host:/data/uploads/
# 2. 跑完后再增量同步一次(只传这段时间变化的文件,很快)
rsync -avz --delete /data/uploads/ new-host:/data/uploads/
# 3. 停掉写入服务,最后一次增量(秒级完成),切换流量
要点:N 次增量把停机窗口压缩到最后一次同步的时间(秒级~分钟级),比停机拷 200G 快几个数量级。
十五、Linux 防火墙与性能分析
1. firewalld(CentOS/RHEL/Rocky 默认)
| 命令 | 说明 |
|---|---|
systemctl status firewalld | 查看防火墙状态 |
firewall-cmd --state | 快速看运行状态 |
firewall-cmd --list-all | 查看当前区域所有规则(开了哪些端口一目了然) |
firewall-cmd --add-port=8080/tcp | 临时放行端口(重启失效) |
firewall-cmd --add-port=8080/tcp --permanent | 永久放行(需 reload) |
firewall-cmd --remove-port=8080/tcp --permanent | 移除放行 |
firewall-cmd --add-rich-rule='rule family=ipv4 source address=192.168.1.0/24 port port=3306 protocol=tcp accept' --permanent | 只允许指定网段访问某端口 |
firewall-cmd --reload | 重载使永久规则生效 |
firewall-cmd --list-ports | 只看放行的端口列表 |
经典流程:
--add-port=xxx/tcp --permanent然后--reload。忘记--permanent是重启后规则消失的头号原因。
2. iptables(底层通用)
| 命令 | 说明 |
|---|---|
iptables -L -n -v | 查看规则(-n 数字显示,-v 显示匹配计数) |
iptables -L INPUT -n --line-numbers | 带行号查看(删除规则要用行号) |
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT | 末尾追加放行规则 |
iptables -I INPUT -p tcp --dport 8080 -j ACCEPT | 插入到最前(先匹配先生效,DROP 在前的话 -A 永远不生效) |
iptables -D INPUT 3 | 按行号删除规则 |
iptables -A INPUT -s 192.168.1.100 -j DROP | 封禁某个 IP |
iptables-save > /etc/iptables.rules | 保存规则 |
# 排查套路:先看 INPUT 链里有没有 REJECT/DROP 挡在你的 ACCEPT 前面
iptables -L INPUT -n -v --line-numbers
# 若 default policy 是 DROP,必须显式 ACCEPT 才能通
3. ufw(Ubuntu 默认)
| 命令 | 说明 |
|---|---|
ufw status verbose | 查看状态与规则 |
ufw enable / disable | 启用/停用 |
ufw allow 22/tcp | 放行端口 |
ufw allow from 192.168.1.0/24 to any port 3306 | 只允许指定网段访问 |
ufw deny from 1.2.3.4 | 封禁 IP |
ufw delete allow 8080/tcp | 删除规则 |
ufw status numbered | 带编号列出(删除用编号更准确) |
4. 性能分析命令速查
CPU:
| 命令 | 说明 | 关注点 |
|---|---|---|
top | 实时总览 | %Cpu(s) 行:us 高=应用忙,sy 高=内核忙,wa 高=等 IO |
top -H -p <PID> | 看进程内线程 | 定位是哪个线程吃 CPU |
vmstat 1 5 | 每秒采样共5次 | r 列(排队进程数)持续 > 核数 = CPU 不够 |
mpstat -P ALL 1 | 每核占用 | 单核 100% 其他闲着 = 应用是单线程瓶颈 |
pidstat 1 | 各进程 CPU | 需 sysstat 包 |
内存:
| 命令 | 说明 | 关注点 |
|---|---|---|
free -h | 内存总览 | available 列才是真实可用(buff/cache 可回收) |
cat /proc/meminfo | 详细内存信息 | — |
| `ps aux –sort=-%mem | head` | 按内存排序的进程 |
| `dmesg | grep -i “killed process”` | 查 OOM Killer 记录 |
磁盘 IO:
| 命令 | 说明 | 关注点 |
|---|---|---|
iostat -xz 1 | 磁盘 IO 详情 | %util 接近 100% = 磁盘繁忙;await 高 = IO 延迟大 |
iotop -o | 只看正在做 IO 的进程 | 找出谁在写盘 |
df -h / df -i | 空间 / inode 占用 | 磁盘没满但写不了?查 inode! |
网络与系统级:
| 命令 | 说明 | 关注点 |
|---|---|---|
sar -n DEV 1 | 网卡流量历史/实时 | 需 sysstat,可回溯历史 |
ss -s | 连接数汇总 | TIME_WAIT 是否爆多 |
ss -tan state time-wait | 查看 TIME_WAIT 连接 | — |
dmesg -T | 内核日志(带时间) | 硬件错误、OOM、网卡 down |
strace 与 lsof(进程行为透视):
| 命令 | 说明 | 常用示例 |
|---|---|---|
strace | 跟踪系统调用 | strace -p <PID>(挂载到运行中的进程) |
strace -c -p | 统计系统调用耗时分布 | 快速判断卡在哪类调用 |
strace -e | 只跟踪指定调用 | strace -e openat,connect -p <PID> |
lsof -p <PID> | 进程打开的文件 | 看句柄泄露 |
lsof -i :8080 | 谁占用了端口 | 比 netstat 更直观 |
| `lsof | grep deleted` | 已删除但仍被占用的文件 |
lsof -u root / lsof /path | 按用户/文件查 | — |
5. 生产实战案例
案例一:服务端口在监听,外部却连不上
背景:应用启动正常,ss -tlnp 显示 8080 已监听,本机 curl 通,外部就是连不上。
排查顺序(由近及远):
# 1. 确认监听地址是 0.0.0.0 而不是 127.0.0.1(只监听回环 = 外部永远不通)
ss -tlnp | grep 8080
# 2. 查本机防火墙
firewall-cmd --list-all # CentOS
iptables -L INPUT -n -v # 通用
ufw status # Ubuntu
# 3. 云服务器必查安全组(控制台操作,最容易忘!)
# 4. 中间链路:公司出口防火墙 / 上游 ACL
结论:本案例是云安全组没放行 8080。经验:先确认监听地址 → 本机防火墙 → 云安全组 → 中间网络设备,按顺序十分钟内必定位。
案例二:CPU 100% 定位到具体线程
背景:Java 服务 CPU 飙到 300%,需定位到具体代码。
# 1. 找到吃 CPU 的进程
top # 记下 PID 12345
# 2. 看进程内哪个线程在跑
top -H -p 12345 # 记下线程 TID 12399
# 3. 线程号转十六进制(jstack 里用十六进制)
printf '%x\n' 12399 # 输出 3087
# 4. 抓线程栈,找对应线程在干什么
jstack 12345 | grep -A 30 3087
通用服务(非 Java)用 strace -p <PID> 看进程卡在哪个系统调用:频繁 futex = 锁竞争;read 不动 = 等下游响应。
案例三:磁盘没满却写不进文件
背景:应用报 No space left on device,df -h 显示还有 40% 空间。
# 真相一:inode 耗尽(海量小文件场景)
df -i # IUse% 100% = inode 用光
# 解决:找到小文件最多的目录清理
find / -xdev -type d -exec sh -c 'echo "$(ls -A "$1" | wc -l) $1"' _ {} \; 2>/dev/null | sort -rn | head
# 真相二:文件删了但进程还占着(空间不释放)
lsof | grep deleted # 找到占用进程,重启它或 truncate 释放
本案例是日志服务 delete 了旧日志但没释放句柄,lsof | grep deleted 一眼定位,重启进程后空间恢复。
十六、磁盘 LVM 与 openssl 证书
1. LVM 基础概念
物理盘/分区 (PV) → 卷组 (VG) → 逻辑卷 (LV) → 文件系统 (xfs/ext4)
/dev/sdb vg_data lv_app 挂载到 /app
| 层级 | 创建 | 查看 | 扩容 |
|---|---|---|---|
| PV 物理卷 | pvcreate /dev/sdb | pvs / pvdisplay | — |
| VG 卷组 | vgcreate vg_data /dev/sdb | vgs / vgdisplay | vgextend vg_data /dev/sdc |
| LV 逻辑卷 | lvcreate -n lv_app -L 100G vg_data | lvs / lvdisplay | lvextend -L +50G /dev/vg_data/lv_app |
2. LVM 在线扩容实战(生产救急流程)
# ======== 场景 A:VG 里还有剩余空间,直接扩 LV ========
vgs # 看 VFree 列有没有剩余
lvextend -L +50G /dev/vg_data/lv_app # 扩 50G(或 -l +100%FREE 全用完)
# 扩容文件系统(关键区别!)
xfs_growfs /app # XFS:在线扩,参数是挂载点
resize2fs /dev/vg_data/lv_app # ext4:在线扩,参数是设备路径
# 判断文件系统类型:df -T /app 或 lsblk -f
# ======== 场景 B:VG 满了,先加新盘再扩 ========
lsblk # 确认新盘识别到了(如 /dev/sdc)
pvcreate /dev/sdc # 1. 新盘做成 PV(不分区直接用整盘也行)
vgextend vg_data /dev/sdc # 2. 加入卷组
lvextend -l +100%FREE /dev/vg_data/lv_app # 3. LV 用完所有剩余空间
xfs_growfs /app # 4. 扩文件系统
云服务器扩容特别注意:云平台扩容磁盘后,先让系统识别新容量:
# 分区盘:扩展分区表(sda 的第 3 个分区为例)
yum install -y cloud-utils-growpart # 或 apt install cloud-guest-utils
growpart /dev/sda 3
# 然后按上面流程:pvresize /dev/sda3 → lvextend → xfs_growfs
pvresize /dev/sda3
3. 磁盘挂载与 fstab
# 新盘完整上线流程
lsblk # 1. 看新盘名(如 /dev/sdb)
fdisk /dev/sdb # 2. 分区(n→p→默认→w),或直接整盘格式化
mkfs.xfs /dev/sdb1 # 3. 格式化
mkdir /data
mount /dev/sdb1 /data # 4. 临时挂载
# 5. 写入 /etc/fstab 实现开机自动挂载
blkid /dev/sdb1 # 先查 UUID(推荐用 UUID 而非设备名,防盘序漂移)
# fstab 行格式:
# UUID=xxxx-xxxx /data xfs defaults 0 0
# 6. 改完 fstab 必做验证(写错会导致开不了机!)
mount -a # 无报错 = 配置正确
df -h | grep data
| 命令 | 说明 |
|---|---|
lsblk -f | 块设备+文件系统+UUID 一览 |
blkid | 查分区 UUID |
mount -a | 按 fstab 挂载所有(验证 fstab 的标准动作) |
findmnt /data | 查看挂载详情与来源 |
umount /data | 卸载(busy 时用 lsof /data 找占用进程) |
4. openssl 证书查看(高频)
| 命令 | 说明 |
|---|---|
openssl x509 -in cert.pem -text -noout | 查看证书完整内容 |
openssl x509 -in cert.pem -noout -dates | 只看有效期(最常用) |
openssl x509 -in cert.pem -noout -subject -issuer | 看颁发给谁/谁颁发的 |
openssl s_client -connect baidu.com:443 -servername baidu.com | 查看线上网站证书(Ctrl+C 退出) |
openssl s_client -connect host:443 2>/dev/null | openssl x509 -noout -dates | 一条命令查线上证书到期时间 |
openssl verify cert.pem | 验证证书有效性 |
openssl rsa -in key.pem -check | 验证私钥 |
openssl x509 -in cert.pem -noout -modulus | openssl md5 | 证书与私钥是否配对(与下条输出一致即配对) |
openssl rsa -in key.pem -noout -modulus | openssl md5 | 同上 |
5. 证书生成与格式转换
# 生成自签证书(测试环境用)
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes \
-subj "/CN=test.example.com"
# 生成带 SAN 的自签证书(多域名/IP,浏览器不报警告的关键)
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes \
-subj "/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:*.example.com,IP:192.168.1.10"
# 生成 CSR(申请正式证书)
openssl req -new -newkey rsa:2048 -keyout server.key -out server.csr -nodes
# 格式转换
openssl x509 -in cert.pem -outform DER -out cert.der # PEM → DER
openssl x509 -in cert.der -inform DER -out cert.pem # DER → PEM
openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.pfx # 合成 PFX(Windows/IIS 用)
openssl pkcs12 -in cert.pfx -out cert.pem -nodes # PFX 拆出 PEM
6. 生产实战案例
案例一:/data 目录 95% 告警,云盘在线扩容不停机
背景:阿里云 ECS 数据盘 500G 告警,业务要求不中断。
# 1. 云控制台把云盘从 500G 扩容到 1T(在线操作)
# 2. 系统侧识别新容量(盘是 /dev/vdb,LVM 分区是 /dev/vdb1)
growpart /dev/vdb 1 # 扩展分区表
pvresize /dev/vdb1 # PV 识别新空间
vgs # VFree 已多出 500G
lvextend -l +100%FREE /dev/vg_data/lv_data
xfs_growfs /data # XFS 在线扩容,秒完
df -h /data # 确认已变 1T
全程业务无感知。要点:控制台扩 → growpart → pvresize → lvextend → xfs_growfs,五步缺一不可。
案例二:证书过期引发的全站告警
背景:HTTPS 证书凌晨过期,监控全红。事后建立证书巡检机制。
# 批量检查所有域名证书剩余天数,小于 30 天告警(加入 crontab 每日执行)
for domain in api.example.com www.example.com admin.example.com; do
days=$(( ($(date -d "$(openssl s_client -connect $domain:443 -servername $domain 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)" +%s) - $(date +%s)) / 86400 ))
echo "$domain 剩余 $days 天"
[ $days -lt 30 ] && echo "【告警】$domain 证书即将过期!"
done
经验:证书更换后必须重载服务(nginx -s reload),只换文件不 reload,旧证书还在内存里继续用——这是"明明换了证书还报过期"的经典原因。
十七、systemd、定时任务与监控中间件
1. systemd 服务管理
| 命令 | 说明 |
|---|---|
systemctl start/stop/restart xxx | 启停/重启服务 |
systemctl status xxx | 状态(含最近几行日志) |
systemctl enable xxx | 开机自启(enable --now = 立即启动+自启) |
systemctl disable xxx | 取消自启 |
systemctl daemon-reload | 改了 unit 文件后必跑 |
systemctl cat xxx | 查看服务的 unit 文件内容 |
systemctl edit xxx | 生成覆盖配置(不改原文件,推荐) |
systemctl list-units --failed | 查看失败的服务 |
systemctl is-active xxx / is-enabled | 脚本中判断状态 |
2. 编写 unit 服务文件(把程序托管给 systemd)
# /etc/systemd/system/myapp.service
[Unit]
Description=My Go Application
After=network.target mysql.service # 依赖:网络和数据库就绪后再启动
[Service]
Type=simple # 前台进程用 simple(不要 daemonize)
User=app # 运行用户(别用 root)
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/server --config /opt/myapp/config.yaml
Restart=on-failure # 崩溃自动重启(always 则无论如何都重启)
RestartSec=5 # 重启前等 5 秒,避免疯狂刷重启
LimitNOFILE=65535 # 文件句柄上限(高并发服务必调)
Environment="GIN_MODE=release" # 环境变量
# 日志交给 journald,用 journalctl 查看
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target # 开机自启挂到多用户模式
上线四步:
systemctl daemon-reload # 1. 加载新 unit
systemctl enable --now myapp # 2. 启动并设自启
systemctl status myapp # 3. 确认 active (running)
journalctl -u myapp -f # 4. 跟踪日志确认正常
3. journalctl 日志深入
| 命令 | 说明 |
|---|---|
journalctl -u myapp | 看某服务日志 |
journalctl -u myapp -f | 实时跟踪 |
journalctl -u myapp --since "1 hour ago" | 最近1小时 |
journalctl -u myapp --since "2026-07-27 10:00" --until "2026-07-27 11:00" | 时间段 |
journalctl -u myapp -p err | 只看 error 及以上级别 |
journalctl -u myapp -b | 只看本次启动以来的日志(-b -1 上次启动) |
journalctl --disk-usage | 日志占了多少磁盘 |
journalctl --vacuum-time=7d | 清理7天前的日志 |
4. crontab 定时任务
# 时间格式:分 时 日 月 周
# ┌──────── 分钟 (0-59)
# │ ┌────── 小时 (0-23)
# │ │ ┌──── 日 (1-31)
# │ │ │ ┌── 月 (1-12)
# │ │ │ │ ┌ 周 (0-7, 0和7都是周日)
# * * * * * 命令
| 写法 | 含义 |
|---|---|
*/5 * * * * | 每 5 分钟 |
0 2 * * * | 每天凌晨 2 点 |
0 2 * * 0 | 每周日凌晨 2 点 |
0 */4 * * * | 每 4 小时整点 |
0 9-18 * * 1-5 | 工作日 9~18 点每小时 |
30 3 1 * * | 每月 1 号 3:30 |
@daily / @weekly / @reboot | 每天 / 每周 / 开机时 |
crontab -e # 编辑当前用户任务
crontab -l # 列出任务
# 系统级任务目录:/etc/crontab、/etc/cron.d/
# 日志重定向(默认发邮件,不处理就找不着输出):
*/5 * * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
crontab 三大经典坑:
- 环境变量差异:cron 环境极简(没有完整的 PATH),脚本里命令写绝对路径(
/usr/bin/mysqldump),或在 crontab 顶部加PATH=/usr/local/bin:/usr/bin:/bin - % 是特殊字符:命令里的
%要转义\%,如date +\%F - 脚本没执行权限:
chmod +x backup.sh,且脚本首行写#!/bin/bash
5. PromQL 监控查询(Prometheus/Grafana)
| 查询 | 说明 |
|---|---|
up | 各采集目标存活状态(1 活 0 死) |
up == 0 | 只看挂掉的 |
rate(http_requests_total[5m]) | 5分钟内 QPS(counter 型指标必配 rate) |
increase(http_requests_total[1h]) | 1小时请求总量 |
sum(rate(http_requests_total[5m])) by (job) | 按 job 聚合 QPS |
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) | CPU 使用率 % |
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 | 内存使用率 % |
(1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes) * 100 | 磁盘使用率 % |
rate(node_network_receive_bytes_total{device!~"lo"}[5m]) * 8 | 网卡入方向带宽(bps) |
topk(5, rate(http_requests_total[5m])) | QPS 最高的前 5 个实例 |
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) | P99 延迟 |
记忆要点:计数器(_total 结尾)必须套
rate()/increase();仪表盘数值用 gauge 直接查;告警阈值常用> 80这类比较表达式。
6. Kafka 常用命令
# ======== Topic 管理 ========
kafka-topics.sh --bootstrap-server host:9092 --list # 列出所有 topic
kafka-topics.sh --bootstrap-server host:9092 --describe --topic mytopic # 详情:分区/副本/ISR
kafka-topics.sh --bootstrap-server host:9092 --create --topic mytopic \
--partitions 3 --replication-factor 2 # 创建
kafka-topics.sh --bootstrap-server host:9092 --alter --topic mytopic \
--partitions 6 # 扩分区(只能加不能减)
# ======== 生产/消费测试 ========
kafka-console-producer.sh --bootstrap-server host:9092 --topic mytopic # 控制台生产
kafka-console-consumer.sh --bootstrap-server host:9092 --topic mytopic \
--from-beginning # 从头消费
# ======== 消费组(堆积排查核心)========
kafka-consumer-groups.sh --bootstrap-server host:9092 --list # 所有消费组
kafka-consumer-groups.sh --bootstrap-server host:9092 --describe --group my-group
# 重点看三列:CURRENT-OFFSET(消费到哪)、LOG-END-OFFSET(总量)、LAG(堆积量)
# 重置消费位点(重消费/跳过堆积,需先停消费者)
kafka-consumer-groups.sh --bootstrap-server host:9092 --group my-group \
--topic mytopic --reset-offsets --to-earliest --execute # 重置到最早
# --to-latest 最新 --shift-by 100 前移100条 --to-datetime "2026-07-27T00:00:00.000"
7. RabbitMQ 常用命令
| 命令 | 说明 |
|---|---|
rabbitmqctl status | 节点状态 |
rabbitmqctl list_queues name messages consumers | 队列消息数/消费者数(堆积排查) |
rabbitmqctl list_exchanges / list_bindings | 交换机/绑定关系 |
rabbitmqctl list_connections / list_channels | 连接/通道 |
rabbitmqctl list_users | 用户列表 |
rabbitmqctl add_user app pass + set_permissions -p / app ".*" ".*" ".*" | 建用户并授权 |
rabbitmqctl purge_queue myqueue | 清空队列(危险) |
rabbitmq-plugins enable rabbitmq_management | 开启 Web 管理台(15672 端口) |
8. 生产实战案例
案例一:Go 程序从裸奔到 systemd 托管
背景:生产服务器上的 Go 程序用 nohup 跑着,服务器重启后忘了手动拉起,造成半夜故障。
# /etc/systemd/system/gitlab-sync.service
[Unit]
Description=GitLab Project Sync Tool
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=ops
WorkingDirectory=/opt/gitlab-sync
ExecStart=/opt/gitlab-sync/main --addr https://git.example.com --token-file /etc/gitlab-sync/token
Restart=on-failure
RestartSec=10
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
systemctl daemon-reload && systemctl enable --now gitlab-sync
systemctl status gitlab-sync && journalctl -u gitlab-sync -f
要点:Restart=on-failure 崩溃自愈,enable 开机自启,敏感 token 放文件而非命令行(ps 会泄露)。
案例二:crontab 备份脚本"手动跑正常,定时不执行"
背景:MySQL 备份脚本手动执行成功,cron 里跑了但备份文件是空的。
# 排查:cron 日志里找执行记录
grep backup /var/log/cron # CentOS
journalctl -u crond | grep backup
# 原因:cron 的 PATH 极简,mysqldump 找不到
# 修复:脚本里写绝对路径 + crontab 顶部声明 PATH
PATH=/usr/local/bin:/usr/bin:/bin
0 2 * * * /usr/bin/mysqldump -uroot -p'xxx' appdb | /bin/gzip > /backup/appdb-$(date +\%F).sql.gz
注意 % 已转义为 \%。教训:cron 排错三板斧——查 cron 日志确认执行了没有、加输出重定向看报错、命令写绝对路径。
案例三:Kafka 消费堆积 100 万条紧急处理
背景:告警消费者 LAG 持续增长,下游处理不过来。
# 1. 确认堆积规模与分布
kafka-consumer-groups.sh --bootstrap-server kafka:9092 --describe --group order-group
# 输出关键:各分区 LAG 列,看是均匀堆积还是个别分区热点
# 2. 判断原因:
# - 生产速率 > 消费速率 → 临时扩容消费者实例数(不超分区数)
# - 消费逻辑慢(下游 DB 慢) → 优化消费端,或临时跳过非关键消息
# 3. 紧急止血:确认可丢弃时,重置位点到最新(会跳过堆积消息!)
kafka-consumer-groups.sh --bootstrap-server kafka:9092 --group order-group \
--topic order-events --reset-offsets --to-latest --execute
要点:先看 LAG 分布判断热点分区,扩消费者不能超分区数,重置位点前必须确认业务允许丢消息。
十八、运维安全红线与通用注意事项
本章是全文档的“保险丝”:前面各章教你怎么干活,这一章教你怎么不出事。生产环境一次误操作的代价,远超十次正确操作的收益。
1. 高危命令红线清单
| 高危命令 | 危害 | 安全替代/防护措施 |
|---|---|---|
rm -rf / rm -rf /* | 删根,系统瞬间报废 | 删除前 pwd 确认路径;变量拼接路径先 echo 看展开结果:rm -rf ${DIR}/* 在 DIR 为空时等于删根! |
rm -rf ./* 在错误目录执行 | 当前目录全没 | 先 pwd 再 ls 确认;重要机器 alias rm='rm -i' |
mkfs.xfs /dev/sda 敲错盘符 | 格式化系统盘 | 执行前 lsblk 三连确认;生产数据盘操作需双人复核 |
dd if=... of=/dev/sdX | 覆盖磁盘,号称“磁盘毁灭者” | of 目标敲三遍再回车 |
chmod -R 777 / | 全系统权限混乱,SSH 直接失效 | 权限操作精确到目录,禁用 777 陋习,用 755/644 + chown |
kill -9 起手就用 | 进程没机会清理现场(临时文件、锁、事务) | 先 kill(TERM)等 10 秒,无效再 -9;数据库类进程慎 -9 |
iptables -F / firewall-cmd --panic-on | 清空规则,远程连接立即中断 | 远程操作防火墙先加放行自己的规则,或挂 at 定时恢复任务 |
> file 重定向到正在使用的文件 | 瞬间清空文件(比 rm 更隐蔽) | 写日志用 >> 追加;确认 > 的目标 |
shutdown/reboot 敲错窗口 | 把生产机重启了 | 多终端窗口给生产机设红色背景/标题;执行前 hostname 确认 |
DROP DATABASE / TRUNCATE | 数据不可逆删除 | 操作前必出备份文件;生产库默认用只读账号登录,写操作换账号 |
git push --force 到 main | 团队历史被覆盖 | 仓库设置保护分支禁强推;只用 --force-with-lease |
kubectl delete ns xxx | 命名空间内资源全删 | 生产集群 kubeconfig 与测试集群分开存放;加 --dry-run=server 先验证 |
docker system prune -a --volumes | 镜像+数据卷全清 | 生产机禁用;清理用精确的 rm/rmi |
redis-cli FLUSHALL | 缓存全清,流量瞬间打穿数据库 | 生产 redis.conf 重命名禁用:rename-command FLUSHALL "" |
| `:(){ : | :& };:` | fork 炸弹,瞬间耗光系统 |
2. 变更操作六步规范
1. 评估影响:改什么、影响谁、最坏情况是什么、有没有更稳的替代方案
2. 备份先行:配置文件 cp 一份(带日期后缀)、数据先导出、网络设备 save + 导出配置
3. 留好退路:远程网络操作挂 reload/定时重启兜底;想清“万一挂了怎么回滚”
4. 低峰执行:避开业务高峰;大变更走审批并通知相关人员值守
5. 小步验证:能改一台就不改一批;每步操作后立即验证,不对就回退
6. 记录复盘:操作内容、时间、结果写进变更记录;出事故先恢复再定位,事后复盘
3. 备份 3-2-1 原则
| 原则 | 说明 | 落地示例 |
|---|---|---|
| 3 份副本 | 原始数据 + 至少 2 份备份 | 生产库 + 每日全备 + binlog 增量 |
| 2 种介质 | 不同存储介质/位置 | 本地磁盘 + 对象存储(OSS/S3) |
| 1 份异地 | 至少 1 份在异地,防机房级灾难 | 备份同步到异地机房/异区云存储 |
备份的有效性 = 最近一次成功恢复演练的时间。没恢复过的备份不算备份,每季度至少做一次恢复演练。
4. 远程操作保命三件套
# 1. 确认自己在哪(多开窗口时每次操作前默念)
hostname && whoami && pwd
# 2. 危险操作前先演练输出
ls /data/old_logs/*.log # 先看会删哪些,确认后再把 ls 换成 rm
# 3. 网络/防火墙远程变更,先挂“后悔药”定时任务
echo "iptables-restore < /root/iptables.bak" | at now + 10 minutes
# 改完确认没问题再 atrm 取消任务;改挂了 10 分钟后自动恢复
5. 权限与安全基线
- 最小权限:日常操作用普通账号 + sudo,不直接登录 root;应用账号只授业务所需权限
- 生产与测试隔离:不同终端配色/主机名前缀;生产 kubeconfig、数据库密码分开管理
- 密钥优于密码:SSH 禁用密码登录(
PasswordAuthentication no),密钥 + 跳板机 - 敏感信息不进命令行:密码/token 会被
history、ps看到,用配置文件或环境变量 - 及时回收:离职/转岗人员账号、临时开放的防火墙端口、调试用的
--privileged容器,用完即收
6. 故障应急心态与流程
第一优先级:恢复业务(重启、回滚、切流量),不是找 root cause
第二优先级:保留现场(日志、进程列表、监控截图先存下来,再动手清理)
第三优先级:复盘改进(写故障报告,落实到监控/流程/文档,防止复发)
排障通用思路(自底向上逐层排除):
物理层(机器活着吗)→ 网络层(ping/通吗)→ 系统层(资源满吗)
→ 中间件层(端口监听吗)→ 应用层(日志报什么)
7. 生产操作 Checklist(可打印贴工位)
□ 我确认当前所在的主机/集群/命名空间是正确的吗?
□ 这个命令的影响范围我清楚吗?(一台?一批?全网?)
□ 有备份吗?备份能恢复吗?(最近验证过吗?)
□ 出错了怎么回滚?回滚方案试过吗?
□ 现在是执行这个操作的合适时间吗?
□ 有人在旁边可以复核/协助吗?(高危操作)
□ 操作完成后,我验证什么来确认成功?