4、Shell脚本基础:变量、条件判断、循环、函数、实战:一键环境检测脚本
Shell脚本,说白了就是你把一堆Linux命令写进一个文件里,让机器自动帮你执行。我刚开始做嵌入式那会儿,总觉得敲命令才够酷,后来项目一多,每次都要手动敲十几条检查命令,烦得不行。嗯,从那以后,我写任何项目的第一件事,就是先写个环境检测脚本。
这一章,咱们就把Shell脚本的核心知识点过一遍。变量怎么用、条件怎么写、循环怎么跑、函数怎么封装。最后,我会带你手写一个实战脚本——一键检测你的交叉编译链、系统库、工具链版本是否齐全。
4.1 变量:存东西的盒子
Shell里的变量,不需要声明类型。你直接赋值就行。我个人习惯用大写字母命名变量名,这样一眼就能看出这是个环境变量或者全局变量。
#!/bin/bash
# 定义一个变量
TOOLCHAIN_PATH="/usr/local/arm-gcc"
# 使用变量,前面加$
echo "我的交叉编译链路径是:$TOOLCHAIN_PATH"
这里有个坑,我刚开始学的时候踩过——赋值号 = 两边不能有空格。你写 TOOLCHAIN_PATH = "/usr/local/arm-gcc" 就错了,Shell会以为你在执行一个叫 TOOLCHAIN_PATH 的命令。
还有一种特殊变量,叫环境变量。比如 $PATH、$HOME。我在项目中经常用 $? 来获取上一条命令的执行结果——0表示成功,非0表示失败。这个在后面的条件判断里非常有用。
4.2 条件判断:让脚本有脑子
条件判断,说白了就是「如果……就……」。Shell里用 if、elif、else、fi 来写。注意结尾的 fi 是 if 倒过来写,这是Shell的特色。
#!/bin/bash
# 检查一个文件是否存在
if [ -f "/usr/local/arm-gcc/gcc" ]; then
echo "交叉编译链已安装"
else
echo "交叉编译链未安装,请先安装"
fi
你想想看,为什么用 [ -f ] 这种写法?其实 [ 是一个命令,等价于 test 命令。所以 [ -f 文件 ] 就是在问「这个文件存在吗?」。
常用的判断条件我列个表给你:
| 表达式 | 含义 |
|---|---|
[ -f 文件 ] |
文件是否存在且为普通文件 |
[ -d 目录 ] |
目录是否存在 |
[ -z 字符串 ] |
字符串是否为空 |
[ 变量1 = 变量2 ] |
两个字符串是否相等 |
[ 数字1 -eq 数字2 ] |
两个数字是否相等 |
-eq、-ne、-gt、-lt,不要用 = 或 !=。我曾经在比较版本号时用错了,结果脚本一直报错,排查了半天才发现是这个问题。
4.3 循环:重复的事情交给机器
循环有两种常用形式:for 循环和 while 循环。我个人更常用 for 循环,因为它写起来更直观。
#!/bin/bash
# 遍历一个列表
for tool in gcc g++ gdb make cmake; do
echo "检查工具:$tool"
which $tool
done
这段代码会依次检查 gcc、g++、gdb、make、cmake 这几个工具是否在系统路径中。我在写环境检测脚本时,经常用这种模式——把要检查的工具名放在一个列表里,然后循环去检测。
while 循环一般用于不确定循环次数的情况。比如读取一个文件的内容:
#!/bin/bash
# 逐行读取一个文件
while read line; do
echo "当前行内容:$line"
done < "依赖列表.txt"
嗯,这里要注意,while read line 这种写法会把文件中的每一行赋值给变量 line,然后执行循环体。我在项目中用它来批量处理日志文件,非常好用。
4.4 函数:把重复代码打包
函数就是把一段代码封装起来,给它起个名字。以后想用这段代码,直接喊名字就行。Shell函数的定义很简单:
#!/bin/bash
# 定义一个函数
check_tool() {
local tool_name=$1
if which $tool_name &>/dev/null; then
echo "$tool_name 已安装"
return 0
else
echo "$tool_name 未安装"
return 1
fi
}
# 调用函数
check_tool "gcc"
check_tool "arm-linux-gnueabihf-gcc"
这里我用了 local 关键字来声明局部变量。为什么?因为如果不加 local,函数里的变量就是全局的,可能会污染外面的变量。我曾经在写一个大型脚本时,因为函数里的变量没加 local,导致两个函数互相覆盖了对方的变量值,查了整整一个下午。
local 声明。
函数的参数通过 $1、$2、$3 来获取。返回值用 return 关键字,但注意返回值只能是 0-255 之间的整数。如果你需要返回字符串,可以用 echo 输出,然后在调用时用 $() 捕获。
4.5 实战:一键环境检测脚本
好了,知识点都讲完了。现在咱们来写一个真正能用的脚本。这个脚本会检测嵌入式开发中最常用的几个工具和库:
- 交叉编译链(arm-linux-gnueabihf-gcc)
- 构建工具(make、cmake)
- 调试工具(gdb、gdbserver)
- 系统库(ncurses、zlib)
先画个流程图,让你对整个脚本的逻辑有个整体认识:
好,现在来看完整的脚本代码:
#!/bin/bash
# ============================================
# 一键环境检测脚本
# 作者:资深嵌入式工程师
# 用途:检测嵌入式开发依赖环境
# ============================================
# 定义颜色变量
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # 无颜色
# 检测结果计数器
PASS_COUNT=0
FAIL_COUNT=0
# 函数:检测单个工具
check_tool() {
local tool_name=$1
local tool_path=$(which $tool_name 2>/dev/null)
if [ -n "$tool_path" ]; then
echo -e "${GREEN}[PASS]${NC} $tool_name 已安装 -> $tool_path"
PASS_COUNT=$((PASS_COUNT + 1))
return 0
else
echo -e "${RED}[FAIL]${NC} $tool_name 未安装"
FAIL_COUNT=$((FAIL_COUNT + 1))
return 1
fi
}
# 函数:检测系统库
check_library() {
local lib_name=$1
# 使用 ldconfig 或 dpkg 检测库文件
if ldconfig -p 2>/dev/null | grep -q "$lib_name"; then
echo -e "${GREEN}[PASS]${NC} 系统库 $lib_name 已安装"
PASS_COUNT=$((PASS_COUNT + 1))
return 0
else
echo -e "${RED}[FAIL]${NC} 系统库 $lib_name 未安装"
FAIL_COUNT=$((FAIL_COUNT + 1))
return 1
fi
}
# 主检测流程
echo "=========================================="
echo " 嵌入式开发环境检测脚本"
echo " 检测时间:$(date)"
echo "=========================================="
echo ""
# 1. 检测交叉编译链
echo "【1/4】检测交叉编译链..."
check_tool "arm-linux-gnueabihf-gcc"
check_tool "arm-linux-gnueabihf-g++"
echo ""
# 2. 检测构建工具
echo "【2/4】检测构建工具..."
check_tool "make"
check_tool "cmake"
echo ""
# 3. 检测调试工具
echo "【3/4】检测调试工具..."
check_tool "gdb"
check_tool "gdbserver"
echo ""
# 4. 检测系统库
echo "【4/4】检测系统库..."
check_library "libncurses"
check_library "libz"
echo ""
# 输出汇总报告
echo "=========================================="
echo " 检测报告"
echo " 通过:$PASS_COUNT 失败:$FAIL_COUNT"
echo "=========================================="
if [ $FAIL_COUNT -eq 0 ]; then
echo -e "${GREEN}恭喜!所有依赖环境已就绪。${NC}"
exit 0
else
echo -e "${YELLOW}警告:有 $FAIL_COUNT 项依赖未安装,请先安装后再继续。${NC}"
exit 1
fi
check_env.sh,然后执行 chmod +x check_env.sh 赋予执行权限,最后运行 ./check_env.sh 即可。
这个脚本里,我用了几个小技巧:
- 颜色输出:用
\033[0;32m这样的转义序列,让通过和失败的结果一目了然。 - 计数器:用
PASS_COUNT和FAIL_COUNT统计结果,最后输出汇总报告。 - 函数封装:把检测逻辑封装成函数,以后想增加检测项,只需要调用函数就行,不用重复写代码。
你想想看,如果每次搭建新环境都要手动敲命令去确认,那得多浪费时间?有了这个脚本,一键运行,所有依赖状态清清楚楚。我在项目中每次换新电脑或者搭建新服务器,第一件事就是跑这个脚本。
check_library 函数使用了 ldconfig -p 来检测库文件。如果你的系统没有 ldconfig 命令(比如某些嵌入式板卡),可以改用 dpkg -l 或 rpm -qa 来检测。
好了,这一章的内容就到这里。变量、条件判断、循环、函数,再加上一个完整的实战脚本,你已经掌握了Shell脚本的核心技能。以后写自动化脚本,心里就有底了。
可可精品资料库