运维命令速查手册

覆盖 Linux / Windows / PowerShell / Git / Docker / Kubernetes / 数据库 / Nginx / 正则 / 网络设备(华为·华三·思科)/ SSH / 防火墙 / 磁盘证书 / systemd / 监控中间件的日常查阅与排障手册。

文档结构:命令速查表 → 场景解惑 Q&A → 生产实战案例 → 安全红线,共 18 章。急查问题先用下方速查索引直达章节。

最后更新:2026-07-27


目录


速查索引

遇到问题先看这里,直达对应章节。⚡ = 内含生产实战案例。

应急排障

遇到的问题直达章节
磁盘满了 / 写不进文件(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/logcd ..cd ~(回家目录)、cd -(回上次目录)
pwd显示当前路径pwd
mkdir创建目录mkdir -p a/b/c(递归创建多级目录)
cp复制cp -r dir1 dir2(复制目录)、cp -a(保留权限)
mv移动/重命名mv old.txt new.txtmv 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.txtcat 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.shchmod +x run.sh(加执行权限)
chown修改属主chown user:group filechown -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 -tlnpnetstat -tlnp(查看监听端口及进程)
ifconfig / ip addr查看 IPip addr(新命令)
scp远程拷贝scp file user@host:/path/
ssh远程登录ssh user@host -p 22
telnet / nc测试端口连通nc -zv host 80telnet 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 / unzipzip 格式zip -r a.zip dir/unzip a.zip -d target/
gzip / gunzipgz 单文件压缩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/Ubuntuaptsudo apt updatesudo apt install nginxapt search xxxsudo apt remove xxx
CentOS/RHELyum / dnfyum install -y nginxyum list installed
通用systemctlsystemctl 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:\Userscd ..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 /ftaskkill /im notepad.exe /f
systeminfo系统详细信息`systeminfo
hostname主机名
whoami当前用户whoami /groups(查看所属组)
set查看/设置环境变量set PATHsetx 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 /allipconfig /flushdns(清DNS缓存)
ping测试连通性ping -t baidu.com(持续ping,Ctrl+C 停止)
tracert路由追踪tracert baidu.com
netstat端口与连接`netstat -ano
nslookupDNS 查询nslookup baidu.com
arpARP 缓存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-ChildItemls/dir/gci列目录gci -Recurse -Filter *.log
Get-Contentcat/type读文件cat app.log -Tail 50 -Wait(类似 tail -f)
Set-Content / Add-Content写/追加文件`“hello”
Copy-Itemcp复制cp -Recurse src dst
Move-Itemmv移动/重命名mv old new
Remove-Itemrm/del删除rm -Recurse -Force dir
New-Itemni新建ni -ItemType Directory test
Get-Locationpwd当前路径
Test-Path判断路径存在Test-Path C:\temp

2. 进程与服务

命令说明示例
Get-Processps进程列表`ps chrome
Stop-Processkill结束进程kill -Name notepad -Force
Get-Servicegsv服务列表`gsv
Restart-Service重启服务Restart-Service wuauserv(需管理员)

3. 网络与系统

命令说明示例
Test-NetConnection测试端口(超好用)Test-NetConnection host -Port 443
Get-NetIPAddressIP 地址Get-NetIPAddress -AddressFamily IPv4
Resolve-DnsNameDNS 查询Resolve-DnsName baidu.com
Invoke-WebRequestcurl/iwrHTTP 请求iwr https://api.com/data
Invoke-RestMethodirmREST 请求(自动解析JSON)irm https://api.com/data
Get-ComputerInfo系统信息
$env:PATH读环境变量$env:PATH -split ';'(分行显示)
Get-Historyh历史命令

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 命令对照表

功能LinuxWindows CMDPowerShell
列目录lsdirGet-ChildItem / ls
切换目录cdcd / cd /dcd
当前路径pwdcd(不带参数)Get-Location
清屏clear / Ctrl+LclsClear-Host / cls
查看文件cattypeGet-Content
实时看日志tail -f无内置Get-Content -Wait -Tail 10
复制cp -rcopy / xcopy / robocopyCopy-Item
移动/重命名mvmove / renMove-Item / Rename-Item
删除rm -rfdel / rd /s /qRemove-Item -Recurse -Force
建目录mkdir -pmkdirNew-Item -ItemType Directory
文本搜索grep -rnfindstr /s /nSelect-String(别名 sls
查进程ps auxtasklistGet-Process
杀进程kill -9 PIDtaskkill /pid PID /fStop-Process -Id PID -Force
查端口占用ss -tlnpnetstat -anoGet-NetTCPConnection -State Listen
测试端口nc -zv host 80telnet host 80Test-NetConnection host -Port 80
查看IPip addripconfigGet-NetIPAddress
下载/请求curl / wgetcurl.exe(Win10+自带)Invoke-WebRequest
环境变量env / echo $PATHset / echo %PATH%$env:PATH
查找命令whichwhereGet-Command
历史命令historyF7 键Get-History
软链接ln -smklinkNew-Item -ItemType SymbolicLink
压缩tar -zcvf无内置Compress-Archive
解压tar -zxvf无内置(tar 新版Win自带)Expand-Archive
文件哈希md5sum / sha256sumcertutil -hashfileGet-FileHash
定时任务crontab -eschtasksRegister-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盘)
可用命令lsgrepfindawksedsshscpcurlvim 等都可用
混合调用可以直接调用 Windows 程序,如 notepad file.txtexplorer .
注意点路径中的反斜杠需转义或改用正斜杠;某些命令(如 pskill)行为和原生 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 devgit 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> 救回

口诀:代码还没 pushreset 改历史;已经 pushrevert 生成新提交。reflog 是后悔药,几乎能找回任何丢失的提交。

5. Stash 暂存

命令说明常用示例
git stash暂存当前改动git stashgit 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 stashgit 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 fetchgit 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.0git 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.25docker pull ubuntu:22.04
docker build构建镜像docker build -t myapp:1.0 .(当前目录 Dockerfile)
docker rmi删除镜像docker rmi nginx:1.25docker 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.0docker load -i myapp.tar
docker history查看镜像分层docker history myapp:1.0(排查镜像为什么大)
docker search搜索 Docker Hubdocker search nginx

2. 容器(Container)生命周期

命令说明常用示例
docker run创建并启动容器见下方常用参数
docker ps查看运行中的容器docker ps -a(含已停止的)、docker ps -q(只显示 ID)
docker stop / start / restart停止/启动/重启docker stop mynginxdocker start -a mynginx(启动并显示输出)
docker rm删除容器docker rm mynginxdocker 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查看 Podkubectl get pods -n prod-o wide(显示节点和IP)、--watch-w(实时刷新)
kubectl get deploy查看 Deploymentkubectl get deploy -o wide
kubectl get svc查看 Servicekubectl 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 prodkubectl 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查看所有资源类型及缩写deploysvcpoing 这些缩写

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\GInnoDB 状态大全(死锁日志在里面)
-- 查看各表占用空间 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按模式查 keyKEYS 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删除 keyDEL 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)
rewriteURL 重写rewrite ^/old/(.*)$ /new/$1 permanent;
try_files按顺序尝试文件,最后用兜底try_files $uri /index.html;
deny / allowIP 访问控制allow 192.168.1.0/24; deny all;
limit_req_zone限流配合 limit_req 限制请求频率

rootalias 易混淆:location /static/ { root /data; } 实际找 /data/static/xxalias /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.logconnect() 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),`+ ?
-PPerl 正则(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 '&lt;&lt;&lt;&lt;&lt;&lt;&lt;' 查 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 / returnundo xxx
思科Switch>enableSwitch#configure terminalSwitch(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-addressMAC 地址表(定位设备接在哪个口)
display arpARP 表(IP 与 MAC 对应关系)
display ip routing-table路由表
display eth-trunk 1链路聚合状态
display stp brief生成树状态(查环路、根桥)
display lldp neighbor briefLLDP 邻居(看对端接的什么设备)
display cpu-usage / display memory-usageCPU / 内存占用
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 口划入 VLANport access vlan 10华为是 port default vlan 10
trunk 放行 VLANport 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 briefVLAN 及成员端口
show mac address-tableMAC 地址表
show arpARP 表
show ip route路由表
show etherchannel summary聚合状态
show spanning-tree生成树(查阻塞口、根桥)
show cdp neighbors detail / show lldp neighbors邻居设备信息
show processes cpu / show processes memoryCPU / 内存
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
保存配置savesave forcewrite memory
进入配置模式system-viewsystem-viewenable + configure terminal
撤销配置undo xxxundo xxxno xxx
接口状态一览display interface brief同华为show ip interface brief
查看 VLANdisplay vlan同华为show vlan brief
查看 MAC 表display mac-address同华为show mac address-table
查看 ARPdisplay arp同华为show arp
查看路由display ip routing-table同华为show ip route
access 口划 VLANport default vlan 10port access vlan 10switchport access vlan 10
trunk 放行 VLANport trunk allow-pass vlan 10port trunk permit vlan 10switchport trunk allowed vlan 10
链路聚合Eth-TrunkBridge-AggregationPort-channel
查邻居display lldp neighbor brief同华为show cdp/lldp neighbors
查光功率display interface transceiver verbosedisplay transceiver diagnosisshow interfaces transceiver
查日志display logbuffer同华为show logging
清空接口计数reset counters interface同华为clear counters
批量接口port-groupinterface 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/1GE2/0/1;思科 gi1/0/1gi2/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 irfIRF 总览:成员、角色、优先级
display irf topology拓扑(环形/链形)及链路状态
display irf link各成员 IRF 口连接详情
display irf configurationIRF 配置
display mad verboseMAD 检测状态
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 package9300 系列整体升级

框式 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思科
盒式技术名iStackIRFStackWise
框式技术名CSSIRFVSS / StackWise Virtual
典型成员上限9 台(按型号)4~10 台(按型号)8~9 台(按系列)
选举依据优先级→运行时长→MAC优先级→运行时长→MAC优先级→MAC
优先级默认值/范围100(1~255)1(1~32)1(1~15)
配置复杂度中(业务口堆叠需配置)较高(编号/端口/激活分步)(即插即用)
脑裂防护MAD(mad detectBFD/LACP/ARP MADStackWise 线缆机制 + PAgP/fast-hello
加入新成员改编号+接线+重启renumber→reboot→绑口→active接线即入(版本需一致)
查看主命令display stackdisplay irfshow switch

6. 堆叠使用注意事项(重要)

规划与实施前:

  1. 版本必须一致:所有成员的软件版本、型号(多数要求同系列)需一致,版本不一致的成员会被拒绝加入或反复重启。新设备入堆前单独升级好版本。
  2. 成员编号先规划:出厂默认编号都一样(华为/思科默认 1、华三默认 1),先单机改好编号再连堆叠线,否则后上的设备会被迫重启改号。
  3. 环形连接优于链形:堆叠线缆首尾相连组成环(如 A→B→C→A),任何一根线断开堆叠都不分裂;链形连接中间断一根就一分为二。
  4. 堆叠口带宽要够:成员间同步所有表项和流量(跨成员转发也走堆叠口),业务口堆叠时至少绑 2 个万兆口,且这些口不能再跑业务。

运行与维护:

  1. 必须配置分裂检测(MAD/双活检测):堆叠线全断时两台成员都会认为自己是主(脑裂),同 IP 同 MAC 的设备并存会冲垮全网。MAD 检测到分裂后会把多余成员的所有业务口关闭,只留一台工作。
  2. 接入层设备跨成员聚合:服务器/下联交换机双上行时,两条链路分别接不同成员并配跨设备聚合(Eth-Trunk/BAGG/Port-channel),这样单台成员故障业务不中断——这才是堆叠最大的价值。
  3. 堆叠后接口编号整体变化:堆叠前写好的脚本、监控、配置基线里的接口名(如 GE0/0/1)要批量更新为带成员号的形式(GE1/0/1)。
  4. 升级要整体规划:堆叠系统一升级就是所有成员重启,业务窗口要留足。跨成员聚合 + 逐台重启(ISSU/平滑升级需型号支持)可减少中断。
  5. 主设备故障切换时间:主挂掉后备机接管,通常秒级收敛;期间管理面(telnet/ssh)会短暂中断,转发面靠跨成员聚合保障不断流。
  6. 堆叠线缆是专用耗材:长度有限(常见 0.5m/1m/3m/5m),只适用于同机柜或相邻机柜,禁止跨楼层/跨机房堆叠;长距离场景改用 M-LAG(华为)/ vPC(思科数据中心)。

容易踩的坑:

  1. 华三改 renumber必须 save 并 reboot 才生效,且旧配置里的接口名全部失效——改号前先 display this 备份配置文本,改号后按新接口名重配。
  2. 思科新成员加入会自动同步主设备配置和 IOS 版本(自动升级/降级),版本差异大时会反复重启,入堆前最好先手动对齐版本。
  3. 华为业务口堆叠的物理口被 port interface ... enable 后,该口原有业务配置会丢失且不能再配业务。
  4. 堆叠分裂恢复后,被 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@hostssh -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/24ping 扫网段(找在线主机)
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=-%memhead`按内存排序的进程
`dmesggrep -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 更直观
`lsofgrep 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/sdbpvs / pvdisplay
VG 卷组vgcreate vg_data /dev/sdbvgs / vgdisplayvgextend vg_data /dev/sdc
LV 逻辑卷lvcreate -n lv_app -L 100G vg_datalvs / lvdisplaylvextend -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 三大经典坑:

  1. 环境变量差异:cron 环境极简(没有完整的 PATH),脚本里命令写绝对路径/usr/bin/mysqldump),或在 crontab 顶部加 PATH=/usr/local/bin:/usr/bin:/bin
  2. % 是特殊字符:命令里的 % 要转义 \%,如 date +\%F
  3. 脚本没执行权限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 ./* 在错误目录执行当前目录全没pwdls 确认;重要机器 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 会被 historyps 看到,用配置文件或环境变量
  • 及时回收:离职/转岗人员账号、临时开放的防火墙端口、调试用的 --privileged 容器,用完即收

6. 故障应急心态与流程

第一优先级:恢复业务(重启、回滚、切流量),不是找 root cause
第二优先级:保留现场(日志、进程列表、监控截图先存下来,再动手清理)
第三优先级:复盘改进(写故障报告,落实到监控/流程/文档,防止复发)

排障通用思路(自底向上逐层排除):
物理层(机器活着吗)→ 网络层(ping/通吗)→ 系统层(资源满吗)
→ 中间件层(端口监听吗)→ 应用层(日志报什么)

7. 生产操作 Checklist(可打印贴工位)

□ 我确认当前所在的主机/集群/命名空间是正确的吗?
□ 这个命令的影响范围我清楚吗?(一台?一批?全网?)
□ 有备份吗?备份能恢复吗?(最近验证过吗?)
□ 出错了怎么回滚?回滚方案试过吗?
□ 现在是执行这个操作的合适时间吗?
□ 有人在旁边可以复核/协助吗?(高危操作)
□ 操作完成后,我验证什么来确认成功?