🎭 日常案例与血泪教训
大家好,我是长安!这是最后一章了,长安把自己工作中的真实案例和血泪教训分享给大家,希望你们能少走弯路。
🎯 本章目标
跟着长安读完这一章,你将收获:
- 真实工作场景中的 Linux 使用案例
- 长安和前人踩过的坑,让你少走弯路
- 一些保命的好习惯
🏢 日常使用案例
案例一:部署一个简单网站
场景:老板说明天要上线一个活动页面,给你一台 Linux 服务器。
# 1. 连接服务器
ssh root@your-server-ip
# 2. 安装 Nginx
sudo apt update
sudo apt install nginx -y
# 3. 确认 Nginx 运行
sudo systemctl status nginx
curl localhost
# 4. 上传网站文件
# 方法一:scp
scp -r ./website/* root@your-server:/var/www/html/
# 方法二:rsync(推荐,支持断点续传)
rsync -avz --progress ./website/ root@your-server:/var/www/html/
# 5. 设置权限
sudo chown -R www-data:www-data /var/www/html/
sudo chmod -R 755 /var/www/html/
# 6. 配置 Nginx(如果需要自定义配置)
sudo vim /etc/nginx/sites-available/default
# 7. 检查配置并重载
sudo nginx -t
sudo systemctl reload nginx
踩坑点:
- 忘记开放防火墙 80 端口 →
sudo ufw allow 80 - 文件权限不对导致 403 错误 → 检查
chown和chmod - 忘记重载配置 →
nginx -t测试后一定要reload
案例二:日志分析找问题
场景:网站访问变慢,需要分析日志找原因。
# 1. 查看实时访问日志
tail -f /var/log/nginx/access.log
# 2. 统计今天访问量
cat /var/log/nginx/access.log | wc -l
# 3. 统计访问最多的 IP(找出是否有人在攻击)
cat /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20
# 4. 统计访问最多的 URL
cat /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
# 5. 统计每分钟请求数(看高峰时段)
cat /var/log/nginx/access.log | awk '{print $4}' | cut -d: -f1-3 | uniq -c
# 6. 找出所有 500 错误
grep " 500 " /var/log/nginx/access.log
# 7. 查看错误日志
tail -100 /var/log/nginx/error.log
# 8. 如果发现某个 IP 恶意访问,封掉它
sudo iptables -A INPUT -s 恶意IP -j DROP
实用技巧:
# 组合使用 - 找出今天 10 点到 11 点的 500 错误
grep "01/Dec/2024:10:" /var/log/nginx/access.log | grep " 500 "
# 使用 awk 提取特定字段
# $1=IP, $4=时间, $7=URL, $9=状态码, $10=响应大小
cat access.log | awk '$9==500 {print $1, $7}'
案例三:定时备份数据库
场景:MySQL 数据库需要每天凌晨自动备份。
# 1. 创建备份脚本
vim ~/backup_mysql.sh
#!/bin/bash
# MySQL 备份脚本
# 配置
BACKUP_DIR="/home/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_USER="root"
DB_PASS="your_password"
DB_NAME="your_database"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 执行备份
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/$DB_NAME-$DATE.sql.gz
# 删除 7 天前的备份
find $BACKUP_DIR -type f -mtime +7 -delete
# 记录日志
echo "[$DATE] 备份完成: $DB_NAME-$DATE.sql.gz" >> $BACKUP_DIR/backup.log
# 2. 添加执行权限
chmod +x ~/backup_mysql.sh
# 3. 测试运行
./backup_mysql.sh
# 4. 添加定时任务
crontab -e
# 添加这行:每天凌晨 3 点执行
0 3 * * * /home/user/backup_mysql.sh
改进版 - 带通知的备份脚本:
#!/bin/bash
# 带通知的备份脚本
BACKUP_DIR="/home/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="your_database"
# 执行备份
if mysqldump -uroot -p'password' $DB_NAME | gzip > $BACKUP_DIR/$DB_NAME-$DATE.sql.gz; then
echo "备份成功" | mail -s "MySQL 备份成功 - $DATE" admin@example.com
else
echo "备份失败!" | mail -s "⚠️ MySQL 备份失败 - $DATE" admin@example.com
fi
案例四:批量处理文件
场景:需要把一堆图片批量重命名、压缩、上传。
# 1. 批量重命名(添加日期前缀)
for file in *.jpg; do
mv "$file" "$(date +%Y%m%d)_$file"
done
# 2. 批量重命名(替换空格为下划线)
for file in *\ *; do
mv "$file" "${file// /_}"
done
# 3. 批量转换图片格式(需要 ImageMagick)
for file in *.png; do
convert "$file" "${file%.png}.jpg"
done
# 4. 批量压缩图片
for file in *.jpg; do
convert "$file" -quality 80 "compressed_$file"
done
# 5. 批量上传到服务器
for file in *.jpg; do
scp "$file" user@server:/path/to/images/
done
# 更高效的批量上传
rsync -avz --progress *.jpg user@server:/path/to/images/
实用的批处理脚本:
#!/bin/bash
# 批量处理图片:压缩 + 重命名 + 归档
INPUT_DIR="./raw"
OUTPUT_DIR="./processed"
mkdir -p $OUTPUT_DIR
count=1
for file in $INPUT_DIR/*.{jpg,png,jpeg}; do
[ -e "$file" ] || continue # 文件不存在则跳过
# 生成新文件名
ext="${file##*.}"
newname=$(printf "image_%03d.%s" $count $ext)
# 压缩并保存
convert "$file" -quality 85 -resize "1920x1080>" "$OUTPUT_DIR/$newname"
echo "处理: $file -> $newname"
((count++))
done
# 打包
tar -czvf processed_images_$(date +%Y%m%d).tar.gz $OUTPUT_DIR/
echo "完成!共处理 $((count-1)) 个文件"
案例五:服务器安全加固
场景:新服务器上线前的安全配置。
# 1. 修改 SSH 端口(防止扫描)
sudo vim /etc/ssh/sshd_config
# 修改 Port 22 为其他端口,如 Port 2222
# 2. 禁止 root 直接登录
# 在 sshd_config 中设置
PermitRootLogin no
# 3. 只允许密钥登录
PasswordAuthentication no
PubkeyAuthentication yes
# 4. 重启 SSH
sudo systemctl restart sshd
# 5. 配置防火墙
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp # SSH 新端口
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
# 6. 安装 fail2ban(防暴力破解)
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# 7. 检查可疑登录
last # 登录记录
lastb # 登录失败记录
cat /var/log/auth.log | grep Failed
安全检查清单:
# 检查监听端口
ss -tlnp
# 检查运行中的服务
systemctl list-units --type=service --state=running
# 检查定时任务
crontab -l
cat /etc/crontab
# 检查用户列表
cat /etc/passwd | grep -v nologin
# 检查 sudo 权限
cat /etc/sudoers
案例六:监控系统资源
场景:写一个简单的监控脚本,资源超限发告警。
#!/bin/bash
# 简单监控脚本 monitor.sh
# 阈值
CPU_THRESHOLD=80
MEM_THRESHOLD=85
DISK_THRESHOLD=90
# 获取资源使用率
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
MEM_USAGE=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100)}')
DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
# 检查并告警
ALERT=""
if (( $(echo "$CPU_USAGE > $CPU_THRESHOLD" | bc -l) )); then
ALERT+="⚠️ CPU 使用率过高: ${CPU_USAGE}%\n"
fi
if (( MEM_USAGE > MEM_THRESHOLD )); then
ALERT+="⚠️ 内存使用率过高: ${MEM_USAGE}%\n"
fi
if (( DISK_USAGE > DISK_THRESHOLD )); then
ALERT+="⚠️ 磁盘使用率过高: ${DISK_USAGE}%\n"
fi
# 发送告警
if [ -n "$ALERT" ]; then
echo -e "$(date)\n$ALERT" >> /var/log/monitor_alert.log
# 可以接入企业微信、钉钉等通知
# curl -X POST -H "Content-Type: application/json" -d '{"text":"'$ALERT'"}' https://webhook.url
fi
添加到 crontab,每 5 分钟检查一次:
*/5 * * * * /home/user/monitor.sh
😱 血泪教训总结
教训一:rm -rf 惨案
🚨 真实案例
有人想删除 /home/user/test 目录,结果多打了个空格:
rm -rf / home/user/test
然后...整个系统就没了 💀
防护措施:
# 1. 给 rm 加保险
alias rm='rm -i'
# 2. 使用 trash-cli 代替 rm
sudo apt install trash-cli
alias rm='trash-put'
# 3. 重要操作前先 echo
echo rm -rf /home/user/test # 先看看要删什么
rm -rf /home/user/test # 确认后再执行
# 4. 使用变量时加引号
DIR="/home/user/test"
rm -rf "$DIR" # 加引号防止变量为空
# 5. 最安全的删除方式
cd /home/user/
rm -rf ./test # 用相对路径
血泪总结:
- 永远不要在 root 权限下随便
rm -rf - 删除前先
ls看看要删什么 - 重要数据一定要有备份
- 考虑用
mv移到临时目录,而不是直接删
教训二:磁盘空间爆满
😰 真实案例
凌晨收到告警,服务器磁盘满了。 查了半天发现是日志文件占了 50GB...
快速处理:
# 1. 找出罪魁祸首
du -sh /* 2>/dev/null | sort -hr | head -10
du -sh /var/log/* | sort -hr | head -10
# 2. 常见占空间的位置
/var/log/ # 日志
/var/cache/ # 缓存
/tmp/ # 临时文件
~/.cache/ # 用户缓存
Docker 镜像 # docker system df
# 3. 快速清理
sudo apt clean # 清理 apt 缓存
sudo journalctl --vacuum-size=100M # 清理 journald 日志
docker system prune -a # 清理 Docker(谨慎)
预防措施:
# 1. 设置日志轮转(logrotate)
cat /etc/logrotate.d/nginx
# 确保配置了 rotate 和 maxsize
# 2. 定期清理任务
echo "0 2 * * 0 root /usr/bin/find /tmp -type f -atime +7 -delete" >> /etc/crontab
# 3. 监控磁盘使用
# 在 crontab 添加
*/30 * * * * [ $(df / | tail -1 | awk '{print $5}' | tr -d '%') -gt 85 ] && echo "磁盘告警" | mail -s "Disk Alert" admin@example.com
教训三:SSH 把自己锁在外面
😭 真实案例
改了 SSH 配置,测试没问题就断开了连接。 结果新配置有问题,再也连不上了...
正确的 SSH 配置修改流程:
# 1. 修改配置前先备份
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
# 2. 保持当前连接,开一个新终端测试
# 千万不要断开当前连接!
# 3. 修改配置
sudo vim /etc/ssh/sshd_config
# 4. 检查配置语法
sudo sshd -t
# 5. 重启 SSH(保持当前连接)
sudo systemctl restart sshd
# 6. 用新终端测试连接
# 能连上再断开旧连接
如果已经被锁在外面:
- 通过云服务商的 VNC/Web 控制台连接
- 恢复备份配置:
cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config - 重启 SSH 服务
教训四:环境变量搞混
🤔 真实案例
在 .bashrc 里改了 PATH,结果写错了,所有命令都找不到了... 连 vim 都用不了。
紧急恢复:
# PATH 变量坏了?用完整路径
/bin/vim ~/.bashrc
/usr/bin/vim ~/.bashrc
# 或者临时恢复 PATH
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# 然后修复配置
vim ~/.bashrc
source ~/.bashrc
正确的修改方式:
# 1. 修改前先备份
cp ~/.bashrc ~/.bashrc.bak
# 2. 添加 PATH 用追加方式,不要直接覆盖
export PATH=$PATH:/new/path # ✅ 追加
export PATH=/new/path # ❌ 覆盖会丢失原有路径
# 3. 在新终端测试
# 不要在当前终端 source,先开新终端看效果
教训五:字符编码问题
🔤 真实案例
脚本在本地跑得好好的,传到服务器就报错。 原因:Windows 换行符是 \r\n,Linux 是 \n
诊断和修复:
# 1. 检查文件类型
file script.sh
# 如果显示 "with CRLF line terminators" 就是换行符问题
# 2. 查看特殊字符
cat -A script.sh
# ^M 表示 \r
# 3. 转换换行符
dos2unix script.sh
# 或者
sed -i 's/\r$//' script.sh
# 4. Vim 中转换
:set ff=unix
:wq
预防措施:
# Git 配置自动转换
git config --global core.autocrlf input
# 使用 EditorConfig
# .editorconfig 文件
[*]
end_of_line = lf
charset = utf-8
教训六:忘记加 nohup
😅 真实案例
跑了一个要执行 3 小时的脚本,SSH 断开后发现进程也没了...
正确的后台运行方式:
# 1. nohup - 最常用
nohup ./long_running_script.sh &
nohup ./script.sh > output.log 2>&1 &
# 2. screen - 可以重新连接
screen -S mysession
./long_running_script.sh
# Ctrl+A, D 断开
# screen -r mysession 重新连接
# 3. tmux - 更现代的选择
tmux new -s mysession
./long_running_script.sh
# Ctrl+B, D 断开
# tmux attach -t mysession 重新连接
# 4. systemd - 正式服务
# 创建 service 文件
sudo vim /etc/systemd/system/myservice.service
tmux 快速入门:
# 安装
sudo apt install tmux
# 新建会话
tmux new -s work
# 断开但不结束
Ctrl+B, D
# 重新连接
tmux attach -t work
# 列出所有会话
tmux ls
教训七:权限设置不当
🔐 真实案例
为了省事把某个目录设成了 777,结果被人植入了木马...
权限最佳实践:
# 1. 最小权限原则
# 文件:644(rw-r--r--)
# 目录:755(rwxr-xr-x)
# 脚本:755(rwxr-xr-x)
# 敏感配置:600(rw-------)
# 2. Web 目录权限
chown -R www-data:www-data /var/www/html
chmod -R 755 /var/www/html
chmod -R 644 /var/www/html/*.php
# 3. SSH 密钥权限
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa # 私钥
chmod 644 ~/.ssh/id_rsa.pub # 公钥
chmod 600 ~/.ssh/authorized_keys
# 4. 永远不要
chmod 777 任何东西 # ❌ 太危险
chmod -R 777 / # ❌ 系统会崩溃
💡 保命好习惯
操作前必做
# 1. 重要操作前先备份
cp config.conf config.conf.bak.$(date +%Y%m%d)
# 2. 删除前先列出
ls target_dir/ # 看看要删什么
rm -rf target_dir/ # 确认后再删
# 3. 修改前先看内容
cat /etc/xxx.conf
vim /etc/xxx.conf
# 4. 批量操作先测试
echo "测试命令" # 先 echo 看看
实际命令 # 确认后再执行
写脚本的好习惯
#!/bin/bash
set -e # 遇到错误立即退出
set -u # 使用未定义变量报错
set -o pipefail # 管道中的错误也捕获
# 或者一行
set -euo pipefail
操作记录
# 1. 用 script 记录操作
script operation_$(date +%Y%m%d).log
# 执行操作...
exit
# 2. 重要变更写注释
vim /etc/nginx/nginx.conf
# 在修改处添加注释
# Modified by xiaoming on 2024-12-01: 增加缓存配置
定期备份
# 重要配置文件
/etc/nginx/
/etc/ssh/
/etc/mysql/
/etc/crontab
# 应用数据
/var/www/
数据库
# 建议使用版本控制
cd /etc
sudo git init
sudo git add .
sudo git commit -m "Initial config"
📝 本章小结
案例清单
| 场景 | 关键技术 |
|---|---|
| 部署网站 | Nginx + scp/rsync + 权限设置 |
| 日志分析 | grep + awk + sort + uniq |
| 定时备份 | Shell 脚本 + crontab |
| 批量处理 | for 循环 + 变量替换 |
| 安全加固 | SSH + 防火墙 + fail2ban |
| 系统监控 | top/free/df + 告警脚本 |
血泪教训
| 教训 | 预防措施 |
|---|---|
| rm -rf 删错 | 使用 trash-cli、先 echo |
| 磁盘爆满 | 监控 + 日志轮转 |
| SSH 锁外面 | 保持连接测试 |
| 环境变量错 | 用追加方式、先备份 |
| 换行符问题 | dos2unix 转换 |
| 忘记 nohup | 使用 tmux/screen |
| 权限太松 | 最小权限原则 |
保命口诀
🛡️ 运维保命口诀
操作之前先备份,
删除之前先看清。
配置改完别断连,
后台任务用 screen。
权限别给 777,
日志定期要清理。
🎯 长安的下一步建议
学到这里,你已经具备了 Linux 的实战能力!长安建议你:
- 多动手实践 - 找个云服务器玩玩
- 记录踩坑经历 - 建立自己的知识库
- 学习进阶内容 - Docker、K8s、自动化运维
- 参与开源项目 - 实战是最好的老师
🔥 长安的最后忠告
不怕犯错,就怕不备份!
每一次翻车都是成长的机会,但前提是你能恢复回来 😄
🎉 恭喜你完成了 Linux 新手村的所有课程!
如果觉得长安的教程对你有帮助,欢迎来编程指南社区交流学习心得,我们一起进步!
—— 编程指南社区 · 长安
