Shell 脚本编程入门:Linux 自动化基础

FreeGuideOnline 最新 2026-06-13

Shell 脚本编程入门:Linux 自动化基础

Shell 脚本是 Linux 系统管理的基石,也是开发者日常自动化的利器。本教程将带你从零开始,掌握编写可执行 Shell 脚本的核心技能。你将学到如何用简单的文本文件串联系统命令,实现批量操作、定时任务和自定义工具。

什么是 Shell 与 Shell 脚本

Shell 是用户和 Linux 内核之间的命令解释器。你在终端输入的命令,正是由 Shell 负责解析执行的。常见的 Shell 有 sh、bash、zsh 等,其中 bash 是绝大多数 Linux 发行版的默认 Shell,也是最通用的脚本语言之一。

Shell 脚本就是将一系列 Shell 命令按顺序写入可执行的文本文件,从而实现任务的自动化。脚本的扩展名通常为 .sh,但关键是文件首行需要声明解释器。

搭建脚本环境与第一个脚本

创建脚本只需三步:

  1. 新建文件,例如 hello.sh
  2. 写入脚本内容。首行必须是指定解释器的 shebang 行:#!/bin/bash
  3. 赋予执行权限chmod +x hello.sh
  4. 运行./hello.sh
#!/bin/bash
# 这是我的第一个 Shell 脚本
echo "Hello, Shell!"

echo 命令用于向终端输出文本。# 开头的行是注释,给自己和他人阅读代码时使用。

变量与字符串操作

变量名通常使用大写,赋值时 等号两边不能有空格

#!/bin/bash
NAME="Alice"
AGE=25
echo "用户: $NAME, 年龄: $AGE"

在字符串中引用变量使用 $变量名${变量名}。当变量名和后面的字符可能混淆时,必须使用大括号:echo "${NAME}_file.txt"

常用字符串操作

  • ${#str} 获取长度
  • ${str:0:5} 提取子串
  • ${str/old/new} 替换第一个匹配
  • ${str//old/new} 替换所有匹配

获取用户输入与传递参数

read 命令

#!/bin/bash
echo -n "请输入你的名字: "
read USER_NAME
echo "你好, $USER_NAME"

-p 选项可直接显示提示语:read -p "名字: " USER_NAME

命令行参数

脚本运行时可以携带参数,在脚本内部通过位置变量访问:

  • $0 脚本自身的名字
  • $1 第一个参数,$2 第二个,以此类推
  • $# 参数个数
  • $@ 所有参数(作为独立字符串)
  • $* 所有参数(作为单个字符串)
#!/bin/bash
echo "脚本名称: $0"
echo "第一个参数: $1"
echo "参数总数: $#"
echo "所有参数: $@"

算术运算

Shell 默认将所有变量视为字符串,需要算术运算时使用 $(( 表达式 )) 或者 let 命令。

#!/bin/bash
A=10
B=3
SUM=$((A + B))
DIFF=$((A - B))
PRODUCT=$((A * B))
QUOTIENT=$((A / B))   # 整数除法
REMAINDER=$((A % B))

echo "和: $SUM, 差: $DIFF, 积: $PRODUCT, 商: $QUOTIENT, 余: $REMAINDER"

若要支持浮点运算,可以配合 bc 命令:

RESULT=$(echo "scale=2; $A / $B" | bc)
echo "浮点结果: $RESULT"

条件判断:if-else 与 test

条件判断使用 [ ][[ ]](bash 推荐使用 [[ ]],功能更强且避免字符拆分)。注意 [ 和变量之间必须有空格

#!/bin/bash
read -p "请输入一个数字: " NUM

if [[ $NUM -gt 10 ]]; then
    echo "数字大于10"
elif [[ $NUM -eq 10 ]]; then
    echo "数字等于10"
else
    echo "数字小于10"
fi

常见比较操作符

  • 数值比较:-eq(等于)、-ne(不等于)、-lt-le-gt-ge
  • 字符串比较:==!=-z(字符串为空)、-n(字符串非空)
  • 文件判断:-f(是普通文件)、-d(是目录)、-x(可执行)、-r(可读)
  • 逻辑运算:&&(与)、||(或)、!(非)

示例:判断文件是否存在。

if [[ -f "/etc/passwd" ]]; then
    echo "文件存在"
fi

循环控制:for 与 while

for 循环

#!/bin/bash
# 遍历列表
for COLOR in red green blue
do
    echo "颜色: $COLOR"
done

# 使用花括号展开生成序列
for i in {1..5}
do
    echo "序号: $i"
done

# C 风格 for (bash 支持)
for (( i=1; i<=5; i++ ))
do
    echo "计数: $i"
done

while 循环

#!/bin/bash
COUNTER=1
while [[ $COUNTER -le 5 ]]
do
    echo "第 $COUNTER 次循环"
    ((COUNTER++))
done

循环控制break 跳出整个循环,continue 跳过本次循环剩余部分。

读取文件与命令输出

循环中处理文件内容时,使用 while read 是最佳做法:

#!/bin/bash
while IFS= read -r line
do
    echo "行内容: $line"
done < "data.txt"

IFS=-r 防止前后空格被删除、防止反斜杠转义。

命令替换将命令的输出存储到变量或直接供循环使用:

FILES=$(ls /var/log)       # 旧式
FILES=`ls /var/log`        # 等价

推荐使用 $() 形式,支持嵌套。

函数:封装与复用

函数让脚本模块化,提高可读性。

#!/bin/bash
# 定义函数
greet() {
    local NAME=$1
    echo "你好, $NAME!"
}
# 调用函数并传参
greet "Bob"
greet "Alice"
  • 函数内使用 local 声明局部变量,避免污染全局空间。
  • 函数参数通过 $1, $2 等取用,与脚本参数类似。
  • 函数可以有返回值,使用 return 返回 0~255 的退出状态码;若需要返回字符串,可通过 echo 配合命令替换捕获。
get_full_name() {
    echo "$1 $2"
}
FULL=$(get_full_name "John" "Doe")
echo "全名: $FULL"

文件处理与 I/O 重定向

  • 输出重定向command > file 覆盖写入;command >> file 追加写入。
  • 输入重定向command < file
  • 错误重定向command 2> error.log 将标准错误写入文件。
  • 合并标准输出和错误command > output.log 2>&1
  • 丢弃输出command > /dev/null 2>&1

特殊文件 /dev/null 是一个黑洞,所有写入它的数据会被丢弃。

常用内置命令与快捷技巧

  • exit 0:正常退出脚本,可传递退出状态。
  • set -e:任何命令退出状态非零时立即停止脚本(严格模式)。
  • set -u:引用未定义变量时报错。
  • set -o pipefail:管道中任一命令失败即视为整个管道失败。
  • 调试模式:bash -x script.sh 可在执行时打印每一条命令,方便排错。
  • 使用 ${var:-default} 提供默认值:NAME=${1:-"匿名"}

实战示例:系统信息报告脚本

下面是一个综合运用所学技巧的脚本,生成一个简单的系统信息报告。

#!/bin/bash
# 系统信息收集脚本
set -euo pipefail

report_file="${1:-report.txt}"
current_date=$(date '+%Y-%m-%d %H:%M:%S')
hostname=$(hostname)
os_version=$(grep PRETTY_NAME /etc/os-release | cut -d '"' -f2)
uptime_info=$(uptime -p)
cpu_cores=$(nproc)
memory_total=$(free -h | awk '/Mem:/ {print $2}')
disk_usage=$(df -h / | awk 'NR==2 {print $5}')

{
    echo "======== 系统报告 ========"
    echo "生成时间: $current_date"
    echo "主机名: $hostname"
    echo "操作系统: $os_version"
    echo "运行时间: $uptime_info"
    echo "CPU 核心数: $cpu_cores"
    echo "内存总量: $memory_total"
    echo "根分区使用率: $disk_usage"
} > "$report_file"

echo "报告已生成: $report_file"

最佳实践速查

  1. 始终使用 shebang#!/bin/bash 确保可移植性。
  2. 变量引用加双引号"$var",防止单词拆分和通配符展开。
  3. 脚本头部加注释:说明功能、用法、作者、日期。
  4. 使用函数:保持脚本结构清晰。
  5. 错误处理:检查关键命令的返回值,或使用 set -e
  6. 避免硬编码:通过配置文件或参数传入变化的值。
  7. 测试与调试:先用 set -x 跟踪执行过程,再正式使用。

Shell 脚本的强大在于能像胶水一样将系统命令无缝衔接。从简单的文件批量重命名,到复杂的定时备份策略,掌握 Shell 就是掌握了 Linux 自动化的钥匙。继续动手编写,遇到问题查阅手册(man bash),你的效率将飞速提升。