当前位置:首页>Linux>Linux常用命令与Shell脚本实战:从手动敲命令到自动化运维

Linux常用命令与Shell脚本实战:从手动敲命令到自动化运维

  • 2026-09-02 15:39:57
Linux常用命令与Shell脚本实战:从手动敲命令到自动化运维

Linux常用命令与Shell脚本实战:从手动敲命令到自动化运维

还在一个个手动敲命令?学会Shell脚本,把重复劳动一键搞定

这项技术到底解决了什么问题?

无论你是开发、测试还是运维,工作中总有一些事情需要登录Linux服务器去做:查看日志、检查磁盘空间、重启服务、批量修改文件、定时备份数据库。如果你每次都手动敲命令,不仅效率低,还容易出错——尤其是在凌晨三点被报警叫起来的时候。

Shell脚本是Linux运维的“自动化开关”。把一系列命令写进一个文件,加上执行权限,就变成了一个可重复运行、不会出错的工具。

本教程将从最常用的Linux命令开始,循序渐进到Shell脚本编程,最后给出几个可以直接用于生产环境的实用脚本。

环境准备

本教程可以在以下任一环境中练习:

  • • macOS终端(自带bash/zsh,大部分命令通用)
  • • Linux服务器(最接近生产环境)
  • • Docker容器(快速启动Linux环境,不怕搞坏):
    docker run -it --name linux-practice ubuntu:22.04 bash# 安装常用工具apt update && apt install -y vim curl wget procps net-tools iputils-ping

以下所有命令在Ubuntu/Debian系Linux上验证通过。

第一步:文件与目录操作(每天用100遍)

# ============================================# 目录导航# ============================================pwd# 显示当前目录cd /var/log             # 切换到指定目录cd ..                   # 返回上级目录cd -                    # 返回上一次所在的目录cd ~                    # 返回home目录# ============================================# 查看文件# ============================================ls -la                  # 列出所有文件(含隐藏文件),详细信息ls -lh                  # 人性化显示文件大小(KB/MB/GB)ls -lt                  # 按修改时间排序tree -L 2               # 树状显示目录结构(限制2层)cat file.txt            # 查看整个文件head -20 file.txt       # 查看前20行tail -20 file.txt       # 查看最后20行tail -f app.log         # 实时追踪日志(Ctrl+C退出)less file.txt           # 分页查看(空格翻页,q退出,/搜索)# ============================================# 文件操作# ============================================cp source.txt dest.txt          # 复制文件cp -r source_dir/ dest_dir/     # 递归复制目录mv old.txt new.txt              # 移动/重命名rm file.txt                     # 删除文件rm -rf dir/                     # 递归强制删除目录(慎用!)mkdir -p a/b/c                  # 递归创建目录touch newfile.txt               # 创建空文件或更新修改时间# ============================================# 文件权限# ============================================chmod +x script.sh              # 添加执行权限chmod 755 script.sh             # 数字方式:rwxr-xr-xchown user:group file.txt       # 修改所有者ls -l file.txt                  # 查看文件权限

第二步:文本处理三剑客(grep、sed、awk)

这三个命令是Linux文本处理的灵魂。掌握它们,你就能在命令行中快速分析和处理任何文本。

grep —— 文本搜索

# 基本搜索grep "ERROR" app.log                    # 查找包含ERROR的行grep -i "error" app.log                 # 忽略大小写grep -v "DEBUG" app.log                 # 排除包含DEBUG的行grep -c "ERROR" app.log                 # 统计匹配行数grep -A 3 "ERROR" app.log              # 显示匹配行及后面3行grep -B 3 "ERROR" app.log              # 显示匹配行及前面3行grep -n "ERROR" app.log                # 显示行号# 正则搜索grep -E "ERROR|FATAL" app.log          # 搜索ERROR或FATALgrep -E "^2026-01-15" app.log          # 搜索指定日期grep -E "[0-9]{3,}" app.log            # 搜索包含3位以上数字的行# 递归搜索grep -r "TODO" src/                     # 递归搜索目录下所有文件grep -rl "TODO" src/                    # 只显示文件名

sed —— 流编辑器(文本替换)

# 替换(最常用)sed 's/old/new/' file.txt              # 每行替换第一个匹配sed 's/old/new/g' file.txt             # 每行替换所有匹配sed -i 's/old/new/g' file.txt          # 直接修改文件(-i)sed -i.bak 's/old/new/g' file.txt      # 修改前备份为.bak# 删除行sed '1d' file.txt                       # 删除第1行sed '1,10d' file.txt                    # 删除第1到10行sed '/ERROR/d' file.txt                 # 删除包含ERROR的行# 插入和追加sed '1i\新行' file.txt                  # 在第1行之前插入sed '1a\新行' file.txt                  # 在第1行之后追加

awk —— 文本分析

# 按列操作(默认以空格/Tab分隔)awk '{print $1}' file.txt               # 打印第1列awk '{print $1, $3}' file.txt           # 打印第1列和第3列awk '{print $NF}' file.txt              # 打印最后一列awk -F':''{print $1}' /etc/passwd     # 以:为分隔符# 条件过滤awk '$3 > 100' data.txt                 # 第3列大于100的行awk '/ERROR/' app.log                   # 包含ERROR的行awk '$3 > 100 {print $1, $3}' data.txt  # 第3列>100时打印第1和第3列# 统计awk '{sum+=$3} END {print sum}' data.txt       # 第3列求和awk '{count++} END {print count}' data.txt      # 统计行数awk '{arr[$1]++} END {for(k in arr) print k, arr[k]}' data.txt  # 按第1列分组统计# 实用示例:分析Nginx日志awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10# 统计访问量TOP 10的IP

第三步:系统监控与进程管理

# ============================================# 磁盘和内存# ============================================df -h                   # 查看磁盘使用情况(-h人性化显示)du -sh /var/log/*       # 查看目录/文件大小free -h                 # 查看内存使用情况# ============================================# 进程管理# ============================================ps aux                  # 查看所有进程ps aux | grep nginx     # 查找指定进程top                     # 实时进程监控(按q退出)htop                    # 更友好的top(需要安装)kill 1234               # 终止进程(PID=1234)kill -9 1234            # 强制终止pkill -f nginx          # 按名称终止进程# ============================================# 网络# ============================================netstat -tlnp           # 查看监听的端口ss -tlnp                # 更现代的netstat替代lsof -i :8080           # 查看哪个进程占用了8080端口curl -I https://example.com  # 查看响应头wget https://example.com/file.tar.gz  # 下载文件# ============================================# 查看日志# ============================================journalctl -u nginx -f  # 实时查看nginx服务日志dmesg | tail -20        # 查看内核日志

第四步:管道、重定向与组合命令

# ============================================# 管道 | :将前一个命令的输出作为后一个命令的输入# ============================================cat app.log | grep ERROR | wc -l# 解释:读取日志 → 过滤ERROR → 统计行数# 实战示例ps aux | grep python | awk '{print $2}' | xargs kill# 解释:找到所有python进程 → 提取PID → 全部终止# ============================================# 重定向:> 覆盖写入,>> 追加写入# ============================================echo"日志开始" > app.log        # 覆盖写入echo"新的一行" >> app.log       # 追加写入# 实战示例:备份 + 压缩tar -czf backup.tar.gz /data/    # 打包压缩mysqldump -u root -p dbname > backup.sql  # 数据库导出# ============================================# 错误处理:2>&1 将错误输出也重定向# ============================================./script.sh > output.log 2>&1    # 标准输出和错误都写入文件./script.sh > /dev/null 2>&1     # 丢弃所有输出(静默执行)

第五步:Shell脚本编程基础

创建一个简单的Shell脚本,然后逐步添加功能。

脚本1:Hello World

创建 hello.sh:

#!/bin/bash# 第一行必须是shebang,指定解释器echo"Hello, World!"echo"当前时间: $(date)"echo"当前用户: $(whoami)"echo"当前目录: $(pwd)"

运行:

chmod +x hello.sh./hello.sh

脚本2:变量与输入

创建 backup.sh:

#!/bin/bash# ============================================# 变量定义# ============================================SOURCE_DIR="/var/log"BACKUP_DIR="/tmp/backups"DATE=$(date +%Y%m%d_%H%M%S)     # 命令替换BACKUP_FILE="$BACKUP_DIR/backup_$DATE.tar.gz"# ============================================# 用户输入($1是第一个参数,$2是第二个...)# ============================================if [ -n "$1" ]; then# -n 检查字符串非空    SOURCE_DIR="$1"fiecho"源目录: $SOURCE_DIR"echo"备份文件: $BACKUP_FILE"# ============================================# 条件判断# ============================================if [ ! -d "$SOURCE_DIR" ]; then# -d 检查目录是否存在echo"错误: 源目录 $SOURCE_DIR 不存在!"exit 1                         # 非0退出码表示失败fimkdir -p "$BACKUP_DIR"# 执行备份tar -czf "$BACKUP_FILE""$SOURCE_DIR" 2>/dev/nullif [ $? -eq 0 ]; then# $? 上一条命令的退出码echo"✅ 备份成功: $BACKUP_FILE"echo"   大小: $(du -sh $BACKUP_FILE | cut -f1)"elseecho"❌ 备份失败!"exit 1fi

条件判断速查表:

文件测试
字符串测试
数值测试
-f file
 文件存在且为普通文件
-z str
 字符串为空
-eq
 等于
-d dir
 目录存在
-n str
 字符串非空
-ne
 不等于
-x file
 文件可执行
str1 = str2
 相等
-gt
 大于
-r file
 文件可读
str1 != str2
 不等
-lt
 小于

脚本3:循环与函数

创建 batch_process.sh:

#!/bin/bash# ============================================# 函数定义# ============================================process_file() {local file="$1"# local声明局部变量echo"处理文件: $file"# 统计行数    lines=$(wc -l < "$file")echo"  行数: $lines"# 查找ERROR    errors=$(grep -c "ERROR""$file" 2>/dev/null || echo 0)if [ "$errors" -gt 0 ]; thenecho"  ⚠️  发现 $errors 个ERROR"fi}# ============================================# for 循环:遍历列表# ============================================echo"=== 遍历文件列表 ==="for file in /var/log/*.log; doif [ -f "$file" ]; then        process_file "$file"fidone# ============================================# while 循环:监控进程# ============================================echo""echo"=== 监控nginx进程(最多10秒)==="count=0while [ $count -lt 10 ]; doif pgrep -f nginx > /dev/null; thenecho"nginx 正在运行"elseecho"nginx 未运行!"fisleep 1    ((count++))                    # 自增done# ============================================# 遍历命令输出# ============================================echo""echo"=== 当前目录下的大文件(>10MB)==="find . -type f -size +10M | whileread -r file; doecho"$(du -sh "$file" | cut -f1)$file"done

脚本4:交互式菜单

创建 menu.sh:

#!/bin/bashshow_menu() {echo""echo"=========================="echo"  系统管理菜单"echo"=========================="echo"1) 查看磁盘使用"echo"2) 查看内存使用"echo"3) 查看CPU负载"echo"4) 查看网络连接"echo"5) 查看最近登录"echo"0) 退出"echo"=========================="}whiletrue; do    show_menuread -p "请选择 [0-5]: " choicecase$choicein        1) df -h ;;        2) free -h ;;        3) uptime ;;        4) ss -tlnp ;;        5) last -n 5 ;;        0) echo"再见!"; exit 0 ;;        *) echo"无效选择,请输入0-5" ;;esacread -p "按回车键继续..."done

第六步:生产环境实用脚本

脚本A:日志清理(保留最近7天)

#!/bin/bash# 文件名: cleanup_logs.sh# 用法: ./cleanup_logs.sh /var/log/appLOG_DIR="${1:-/var/log/app}"RETENTION_DAYS=7if [ ! -d "$LOG_DIR" ]; thenecho"目录不存在: $LOG_DIR"exit 1fiecho"清理 $LOG_DIR 中超过 $RETENTION_DAYS 天的日志..."# 查找并删除deleted_count=0deleted_size=0find "$LOG_DIR" -name "*.log" -mtime +$RETENTION_DAYS | whileread -r file; do    size=$(stat -c%s "$file" 2>/dev/null || echo 0)echo"  删除: $file ($(numfmt --to=iec $size))"rm -f "$file"doneecho"✅ 清理完成"

脚本B:服务健康检查

#!/bin/bash# 文件名: health_check.sh# 用法: ./health_check.shTARGET="${1:-http://localhost:8080/health}"TIMEOUT=5MAX_RETRIES=3check_health() {for i in $(seq 1 $MAX_RETRIES); do        status=$(curl -s -o /dev/null -w "%{http_code}" \            --connect-timeout $TIMEOUT \            --max-time $TIMEOUT \"$TARGET" 2>/dev/null)if [ "$status" = "200" ]; thenecho"✅ 健康检查通过 ($TARGET)"return 0fiecho"⚠️  第${i}次检查失败 (HTTP $status),等待重试..."sleep 2doneecho"❌ 健康检查失败! ($TARGET)"return 1}check_health

脚本C:数据库自动备份

#!/bin/bash# 文件名: db_backup.sh# 用法: 添加到crontab: 0 2 * * * /path/to/db_backup.shDB_NAME="myapp"DB_USER="backup_user"DB_PASS="backup_pass"BACKUP_DIR="/backups/mysql"RETENTION_DAYS=30DATE=$(date +%Y%m%d_%H%M%S)BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"mkdir -p "$BACKUP_DIR"echo"开始备份数据库: $DB_NAME"# 执行备份(使用mysqldump)if mysqldump -u "$DB_USER" -p"$DB_PASS" \    --single-transaction \    --routines \    --triggers \"$DB_NAME" | gzip > "$BACKUP_FILE"; thenecho"✅ 备份成功: $BACKUP_FILE"echo"   大小: $(du -sh $BACKUP_FILE | cut -f1)"elseecho"❌ 备份失败!"exit 1fi# 清理旧备份echo"清理 $RETENTION_DAYS 天前的备份..."find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -deleteecho"✅ 备份任务完成"

第七步:Crontab定时任务

# 编辑crontabcrontab -e# 格式:分 时 日 月 周 命令# ============================================# 示例# ============================================0 2 * * * /scripts/db_backup.sh          # 每天凌晨2点备份0 3 * * 0 /scripts/cleanup_logs.sh       # 每周日凌晨3点清理日志*/5 * * * * /scripts/health_check.sh     # 每5分钟健康检查0 8 * * 1-5 /scripts/daily_report.sh     # 工作日早上8点生成报告# 查看已设置的定时任务crontab -l# 查看crontab日志grep CRON /var/log/syslog

实用技巧与避坑指南

  1. 1. 变量引用养成加引号的习惯:"$file" 而不是 $file。如果文件名包含空格,不加引号会被拆分成多个参数。
  2. 2. set -e 让脚本遇到错误就停止:在脚本开头加上 set -e,任何命令返回非0退出码就立即终止。加上 set -u 则在引用未定义变量时报错,避免变量名拼写错误导致的隐蔽bug。
  3. 3. rm -rf 前先打印确认:在脚本中使用变量拼接的路径执行删除时,先用 echo 打印出目标路径,确认无误后再改为 rm。
  4. 4. 使用shellcheck检查脚本:
    # 安装shellcheck(静态分析Shell脚本的工具)apt install shellcheckshellcheck script.sh
  5. 5. 记录脚本执行日志:
    LOG_FILE="/var/log/script.log"exec 2>&1exec > >(tee -a "$LOG_FILE")# 后续所有输出都会同时显示在终端和写入日志文件

总结

本教程覆盖了从基础命令到生产级Shell脚本的完整学习路径:

层级
内容
掌握程度
基础命令
文件操作、权限、文本处理三剑客
每天使用
系统管理
进程、磁盘、网络、日志
排查问题时使用
Shell编程
变量、条件、循环、函数
编写自动化脚本
生产脚本
日志清理、健康检查、数据库备份
部署到服务器运行

掌握了这些,你就能把日常工作中的重复性操作封装成脚本,把时间省下来做更有价值的事。


最新文章

随机文章