目录
一 shell函数
1 函数的用法
Shell 函数是:
-
命名的命令集合:给一组命令赋予一个名称,便于重复调用
-
脚本中的子程序:类似于其他编程语言中的函数或方法
-
参数化执行单元:可以接收参数并返回结果
-
代码复用机制:避免重复编写相同代码
Shell 函数语法是:
#!/bin/bash
#
sum() { #在大括号里写函数体
命令序列
[ return x ]
}
#调用函数sum
sum
参数 | 说明 |
sum | 函数名 |
{ | 表示函数执行命令的入口,该符号可以与函数名同行也可以在函数名下一行的句首 |
} | 表示函数体结束,两个大括号之间 { } 是函数体 |
命令序列 | 部分可以是任意的shell命令,也可以调用其他函数 |
return | 表示退出函数返回一个退出值,通过返回值判断执行是否成功,也可以用exit终止整个shell脚本 |
(1)两个数求和
应用示例:
#!/bin/bash
#
sum() {
echo "请输入第一个数字:"
read num1
if ! [[ $num1 =~ ^[0-9]+$ ]]; then # ! 用于取反,判断num1是否为整数。+ 任意一个或多个数字^开头,$结尾。
echo "你输入的第一个数不是整数,请重新运行脚本"
return 1
fiecho "请输入第二个数字:"
read num2
if ! [[ $num2 =~ ^[0-9]+$ ]]; then # ! 用于取反,判断num1是否为整数。+ 任意一个或多个数字^开头,$结尾。
echo "你输入的第二个数不是整数,请重新运行脚本"
return 1
fi#计算2数之和
result=$((num1 + num2)) #也可以写成 $( expr num1 + num2 )#输出结果
echo "2数之和为:$result"
}
#调用sum函数
sum
示例验证:
[root@Euler04 ~]# vim aaa.sh
[root@Euler04 ~]# chmod +x aaa.sh
[root@Euler04 ~]# bash aaa.sh
请输入第一个数字:
2
请输入第二个数字:
3
2数之和为:5
[root@Euler04 ~]# bash aaa.sh
请输入第一个数字:
a
你输入的第一个数不是整数,请重新运行脚本
(2)系统资源监控并报警函数
应用示例:
#!/bin/bash
#发送报警信息的函数
send_alert() { #在大括号里写函数体
local message=$1
echo "ALERT: $message"
#这里可以添加发送邮件,短信等报警逻辑
}
#系统资源监控函数
monitor_system_resources() {
local cpu_threshold=$1
local mem_threshold=$2
local interval=$3while true;do
#获取CPU使用率
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $3}')
#获取内存使用率
mem_usage=$(free | awk '/Mem/ {printf("%.2f", $3/$2 * 100)}')if (( $(echo "$cpu_usage > $cpu_threshold" | bc -l) )); then
send_alert "CPU usage ($cpu_usage%)."
fi
if (( $(echo "$mem_usage > $mem_threshold" | bc -l) )); then
send_alert "Memory usage ($mem_usage%)."
fi
sleep "$interval"
done
方向 | 关键点 |
---|---|
参数设计 | 定义监控阈值(CPU/内存/磁盘)、检查间隔、报警方式(日志/邮件/Webhook) |
循环监控 | 使用 while 循环定时检查资源,对比阈值判断是否触发报警 |
报警处理 | 支持多种报警方式(日志、邮件、短信、Webhook),确保问题及时通知管理员 |
示例验证:
[root@Euler04 ~]# vim bb.sh
[root@Euler04 ~]# chmod +x bb.sh
[root@Euler04 ~]# bash bb.sh
ALERT: Memory usage (15.97%).
ALERT: Memory usage (16.04%).
2 函数标量的作用范围
概念总结:
-
局部变量:函数内部使用
local
声明的变量,只在函数内有效 -
全局变量:函数外部定义的变量,整个脚本可见
-
环境变量:使用
export
导出的变量,子进程可见 -
变量遮蔽:局部变量会遮蔽同名的全局变量
应用示例:
#!/bin/bash
#
myfun() {
local i
i=8
echo $!}
i=9
myfun
echo $i
示例验证:
[root@Euler04 ~]# vim bbb.sh
[root@Euler04 ~]# chmod +x bbb.sh
[root@Euler04 ~]# bash bbb.sh9
3 函数的参数
概念总结
-
位置参数:
$1
,$2
, ...,$9
表示第1到第9个参数 -
特殊参数:
-
$0
:脚本/函数名 -
$#
:参数个数 -
$@
:所有参数列表 -
$*
:所有参数组合成一个字符串
-
-
参数扩展:
${1:-默认值}
设置参数默认值
应用示例:
#!/bin/bash
#
mydir="/data" outfile="${mydir}/my.log"
[ -e "${mydir}" ] || mkdir -p ${mydir}appendfile() {
echo "$2" >> "$1"
}
appendfile ${outfile} "first line content"
appendfile ${outfile} "second line content"
示例验证:
[root@Euler04 ~]# vim cc.sh
[root@Euler04 ~]# chmod +x cc.sh
[root@Euler04 ~]# bash cc.sh[root@Euler04 ~]# cat /data/my.log
first line content
second line content
4 递归函数
概念总结:
-
递归函数:函数调用自身
-
必要条件:
-
递归终止条件
-
每次递归向终止条件推进
-
-
注意事项:
-
确保有终止条件,避免无限递归
-
递归深度过大可能导致栈溢出
-
相比迭代效率较低
-
应用示例:
#!/bin/bash
#
#定义递归遍历目录的函数
traverse_directory() {
local dir=$1
#遍历当前目录下的所有文件和文件夹
for itme in "$dir"/*; do
if [ -d "$item" ]; then
#如果是目录,递归调用函数继续遍历
echo "Directory: $item"
traverse_directory "$item"
elif [ -f "$item" ]; then
#如果是文件,输出文件路径
echo "File: $item"
fi
done}
#调用函数,从当前目录开始遍历
traverse_directory "."
二 shell数组
概念:
Shell数组是一种可以存储多个值的变量,在Bash中主要分为两种类型:
-
索引数组(Indexed Arrays):使用数字作为下标(从0开始)
-
关联数组(Associative Arrays):使用字符串作为下标(需要Bash 4.0+)
数组常用定义方法包括以下几种:
方法一:
数组名=( value0 value1 value2 value3......)
方法二:
数组名=( [0]=value [1]=value [2]=value [3]=value......)
方法三:
列表名=“value0 value1 value2 value3......” 数组名=($列表名)
方法四:
数组名[0]=“value” 数组名[1]=“value” 数组名[2]=“value”........
1 获取数组长度
数组的语法
$ { #数组名[ @ ] } 或 $ {#数组名[ * ] }
//@ ,*该数组所有的函数
例子:aaa=( 1 2 3 4 5 6 )
for i in ${ aaa[ @ ] }
do
echo $i
Done
应用示例:
[root@Euler04 ~]# arr_number=(1 2 3 4 5)
[root@Euler04 ~]# arr_length=${#arr_number[*]}
[root@Euler04 ~]# echo $arr_length
5
[root@Euler04 ~]# arr_length_1=${#arr_number[@]}
[root@Euler04 ~]# echo $arr_length_1
5
2 读取某下标赋值
在Shell中读取数组特定下标的值并赋给变量的基本语法是:
variable_name=${array_name[index]} 变量名=${ 元素[ 序列 ] }
应用示例:
[root@Euler04 ~]# arr_index2=${arr_number[2]}
[root@Euler04 ~]# echo $arr_index2
3
3 数组遍历
概念:
数组遍历是指按照一定顺序访问数组中每个元素的过程。在Shell脚本中,遍历数组是处理数组数据的基本操作之一。
数组遍历常用语法:
for element in "${array[@]}"
do
# 处理每个$element
done
特点:
-
${array[@]}
展开为所有数组元素 -
引号保护元素中的空格不被分割
-
保持元素原始值
应用示例:
#!/bin/bash
#
arr_number=(1 2 3 4 5)
for v in ${arr_number[@]}
do
echo $v
done
示例验证:
[root@Euler04 ~]# vim dd.sh
[root@Euler04 ~]# chmod +x dd.sh
[root@Euler04 ~]# bash dd.sh
1
2
3
4 数组切片
概念:
数组切片是指从原数组中提取一个连续的子序列(子数组)。Shell通过特定的语法格式支持数组切片操作,可以方便地获取数组的一部分。
语法:
${array[@]:起始索引:长度} 或 ${array[*]:起始索引:长度}
参数:
-
起始索引:
-
从0开始计数
-
可以是负数(Bash 4.2+),表示从数组末尾开始计算
-
如果省略,默认为0
-
-
长度:
-
要提取的元素个数
-
如果省略,提取从起始索引到数组末尾的所有元素
-
应用示例:
array=("a" "b" "c" "d" "e" "f")
# 从索引1开始取3个元素
echo "${array[@]:1:3}" # 输出: b c d# 从索引2开始到末尾
echo "${array[@]:2}" # 输出: c d e f
5 数组替换
概念:
数组替换是指对数组中的元素进行内容替换操作,生成一个新数组而不改变原始数组。Shell提供了灵活的数组元素替换语法,支持简单的模式匹配和替换。
语法:
# 单个元素替换
${array[index]/模式/替换内容}# 全局替换(所有元素)
${array[@]/模式/替换内容}
应用示例:
fruits=("apple" "banana" "appricot")
# 替换第一个匹配的字符
echo "${fruits[@]/a/A}" # 输出: Apple bAnana Appricot# 使用双斜杠//表示全局替换
echo "${fruits[@]//a/A}" # 输出: Apple bAnAnA Appricot# 使用/#匹配开头
echo "${fruits[@]/#a/A}" # 输出: Apple banana appricot
6 数组删除
概念:
数组删除是指从数组中移除一个或多个元素的操作。在Shell中,数组删除主要分为两种形式:
-
删除单个元素 - 移除数组中指定位置的元素
-
删除整个数组 - 完全移除数组变量
语法:
unset array_name[index] //删除单个元素
unset array_name //删除整个数组
应用示例:
files=("a.txt" "b.jpg" "c.txt")
# 删除所有.txt文件
for i in "${!files[@]}"; do
if [[ "${files[i]}" == *.txt ]]; then
unset files[i]
fi
done
Shell数组删除关键点:
-
使用
unset
命令删除元素或整个数组 -
删除元素后数组变为稀疏
-
不会自动重新索引数组
-
可以删除普通数组和关联数组的元素
-
删除整个数组会完全移除变量
-
实际应用中常配合条件判断进行选择性删除
三 shell脚本调试
基本调试方法:
1.执行时启用调试模式
# 在命令行执行时启用调试
bash -x script.sh # 显示所有执行的命令
bash -v script.sh # 显示原始脚本内容
bash -n script.sh # 只检查语法不执行
2.脚本内启用调试模式
#!/bin/bash
set -x # 开启调试
# 脚本内容...
set +x # 关闭调试
常用调试基本选项:
选项 | 作用描述 |
---|---|
set -x | 打印执行的命令及参数(xtrace) |
set -v | 打印输入的shell命令(verbose) |
set -n | 只读取不执行(语法检查) |
set -e | 命令失败时立即退出(errexit) |
set -u | 使用未定义变量时报错(nounset) |
set -o pipefail | 管道中任一命令失败则整个管道失败 |
应用示例:
#!/bin/bash
set -euxo pipefail# 常用严格模式组合
function divide() {
local numerator=$1
local denominator=$2
echo "DEBUG: numerator=$numerator, denominator=$denominator" >&2
echo $((numerator / denominator))
}main() {
local a=10
local b=0
result=$(divide $a $b)
echo "Result: $result"
}trap 'echo "Error at line $LINENO"' ERR
main
四 总结
Shell函数 | ||
定义 | func_name() { cmds; } 或 function func_name { cmds; } | say_hello() { echo "Hello $1"; } |
参数 | $1 -$n 位置参数,$# 参数个数,$@ 所有参数 | func foo bar → $1=foo , $2=bar |
返回值 | return 返回状态码(0-255),echo 输出结果 | return 0 或 echo "result" |
局部变量 | local var=value 限定函数内作用域 | local count=0 |
Shell数组 | ||
索引数组 | arr=(val1 val2) ,下标从0开始 | colors=("red" "green") ,${colors[0]} → "red" |
关联数组 | declare -A arr=([k1]=v1 [k2]=v2) (Bash 4.0+) | declare -A dict=([name]="Alice") ,${dict[name]} → "Alice" |
常用操作 | ${arr[@]} 所有元素,${#arr[@]} 长度,${arr[@]:1:2} 切片 | echo "${colors[@]:1}" → "green" |
遍历 | for i in "${arr[@]}"; do ... done | for color in "${colors[@]}"; do echo $color; done |
脚本调试 | ||
调试模式 | bash -x script.sh (跟踪执行),set -x (脚本内启用) | set -x 和 set +x 包围调试代码块 |
严格模式 | set -euo pipefail (错误退出+未定义变量报错+管道失败检测) | 脚本开头添加增强安全性 |
调试工具 | shellcheck (静态检查),bashdb (交互调试),trap (错误捕获) | trap 'echo "Error at $LINENO"' ERR |
日志输出 | echo "DEBUG: $var" >&2 (输出到标准错误) | 关键步骤添加变量打印 |
部分核心关联
-
函数+数组:函数内可处理数组参数(
func "${arr[@]}"
),返回数组需通过echo
输出 -
脚本+调试:调试时重点关注函数调用栈和数组传递过程
-
最佳实践:函数封装数组操作,脚本主流程调用,
set -eux
全程监控