Shell 脚本编程入门:Linux 自动化基础
Shell 脚本编程入门:Linux 自动化基础
Shell 脚本是 Linux 系统管理的基石,也是开发者日常自动化的利器。本教程将带你从零开始,掌握编写可执行 Shell 脚本的核心技能。你将学到如何用简单的文本文件串联系统命令,实现批量操作、定时任务和自定义工具。
什么是 Shell 与 Shell 脚本
Shell 是用户和 Linux 内核之间的命令解释器。你在终端输入的命令,正是由 Shell 负责解析执行的。常见的 Shell 有 sh、bash、zsh 等,其中 bash 是绝大多数 Linux 发行版的默认 Shell,也是最通用的脚本语言之一。
Shell 脚本就是将一系列 Shell 命令按顺序写入可执行的文本文件,从而实现任务的自动化。脚本的扩展名通常为 .sh,但关键是文件首行需要声明解释器。
搭建脚本环境与第一个脚本
创建脚本只需三步:
- 新建文件,例如
hello.sh。 - 写入脚本内容。首行必须是指定解释器的 shebang 行:
#!/bin/bash。 - 赋予执行权限:
chmod +x hello.sh。 - 运行:
./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"
最佳实践速查
- 始终使用 shebang:
#!/bin/bash确保可移植性。 - 变量引用加双引号:
"$var",防止单词拆分和通配符展开。 - 脚本头部加注释:说明功能、用法、作者、日期。
- 使用函数:保持脚本结构清晰。
- 错误处理:检查关键命令的返回值,或使用
set -e。 - 避免硬编码:通过配置文件或参数传入变化的值。
- 测试与调试:先用
set -x跟踪执行过程,再正式使用。
Shell 脚本的强大在于能像胶水一样将系统命令无缝衔接。从简单的文件批量重命名,到复杂的定时备份策略,掌握 Shell 就是掌握了 Linux 自动化的钥匙。继续动手编写,遇到问题查阅手册(man bash),你的效率将飞速提升。