1. Shell函数基础概念与语法解析
在Linux系统管理和运维工作中,Shell函数是我们日常脚本编写中不可或缺的利器。简单来说,函数就是一段被命名并可以重复调用的代码块,它能将复杂的操作封装起来,让脚本更加模块化和可维护。
1.1 函数定义格式详解
Shell中定义函数主要有两种标准格式:
第一种是使用function关键字的显式声明方式:
bash复制function service_control {
# 函数体内容
systemctl $1 nginx
}
第二种是省略关键字的简洁声明方式(更符合POSIX标准):
bash复制check_status() {
# 函数体内容
systemctl status nginx
}
这两种方式在实际使用中完全等效,但需要注意几个关键细节:
- 函数名后的小括号
()只是语法形式,不需要也不能包含参数 - 函数体必须用大括号
{}包裹,且开括号{与函数名之间必须有空格 - 函数体内的命令可以像普通脚本一样编写,支持所有Shell特性
提示:建议统一选择一种风格并在团队中保持一致性。个人更推荐第二种方式,因为它兼容性更好且更简洁。
1.2 函数调用与参数传递
调用函数就像执行普通命令一样简单,直接写函数名即可:
bash复制service_control start
Shell函数支持参数传递,在函数内部通过$1、$2等位置参数获取:
bash复制log_message() {
local level=$1
local msg=$2
echo "[$(date)] [$level] $msg" >> /var/log/myscript.log
}
# 调用示例
log_message INFO "Service started successfully"
1.3 变量作用域与local关键字
Shell函数中变量的作用域需要特别注意:
bash复制global_var="outside"
demo_scope() {
local local_var="inside"
global_var="modified"
echo "函数内: $local_var, $global_var"
}
demo_scope
echo "函数外: $local_var, $global_var"
执行结果会是:
code复制函数内: inside, modified
函数外: , modified
关键点:
- 默认情况下函数内修改的变量会影响全局
- 使用
local关键字可以限制变量只在函数内有效 - 建议函数内所有变量都显式声明为local,避免副作用
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 函数在运维场景中的典型应用
2.1 服务管理自动化
正如示例中的nginx控制脚本,这是函数最典型的应用场景。我们可以进一步扩展这个思路:
bash复制manage_service() {
local service=$1
local action=$2
case $action in
start|stop|restart|status)
systemctl $action $service
;;
*)
echo "无效操作: $action"
return 1
;;
esac
}
# 使用示例
manage_service nginx restart
manage_service mysql start
这种封装带来的好处:
- 统一的服务管理接口
- 减少重复代码
- 便于添加日志记录、错误处理等公共逻辑
2.2 日志记录与报警
封装日志记录函数可以大幅提升脚本的可维护性:
bash复制LOG_FILE="/var/log/ops_scripts.log"
log() {
local level=$1
shift
local message="$*"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$timestamp] [$level] $message" | tee -a $LOG_FILE
# 如果是错误级别,额外发送报警
if [ "$level" = "ERROR" ]; then
send_alert "$message"
fi
}
# 使用示例
log INFO "Starting backup process"
log ERROR "Disk space insufficient!"
2.3 配置检查与系统巡检
编写可复用的检查函数:
bash复制check_disk() {
local threshold=${1:-90} # 默认阈值90%
local usage=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%')
if [ $usage -ge $threshold ]; then
log WARNING "磁盘使用率过高: $usage%"
return 1
fi
return 0
}
check_memory() {
local threshold=${1:-90}
local usage=$(free | awk '/Mem/{printf("%d"), $3/$2*100}')
[ $usage -ge $threshold ] && {
log WARNING "内存使用率过高: $usage%"
return 1
}
return 0
}
# 在巡检脚本中调用
check_disk 85 || alert_admin
check_memory 80 || alert_admin
3. Nginx管理脚本进阶实现
3.1 完整功能实现
让我们基于原始示例构建一个更健壮的nginx管理脚本:
bash复制#!/bin/bash
NGINX_CONF="/etc/nginx/nginx.conf"
LOG_DIR="/var/log/nginx"
# 定义颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 检查nginx是否安装
check_installed() {
if ! command -v nginx &> /dev/null; then
echo -e "${RED}错误: Nginx未安装!${NC}"
exit 1
fi
}
# 检查配置语法
check_config() {
if nginx -t &> /dev/null; then
echo -e "${GREEN}配置语法检查通过${NC}"
return 0
else
echo -e "${RED}配置语法错误!${NC}"
nginx -t # 显示具体错误
return 1
fi
}
# 启动nginx
start() {
echo -e "${YELLOW}正在启动Nginx...${NC}"
if systemctl start nginx; then
echo -e "${GREEN}Nginx启动成功${NC}"
return 0
else
echo -e "${RED}Nginx启动失败${NC}"
return 1
fi
}
# 停止nginx
stop() {
echo -e "${YELLOW}正在停止Nginx...${NC}"
if systemctl stop nginx; then
echo -e "${GREEN}Nginx已停止${NC}"
return 0
else
echo -e "${RED}Nginx停止失败${NC}"
return 1
fi
}
# 重启nginx
restart() {
check_config || return 1
echo -e "${YELLOW}正在重启Nginx...${NC}"
if systemctl restart nginx; then
echo -e "${GREEN}Nginx重启成功${NC}"
return 0
else
echo -e "${RED}Nginx重启失败${NC}"
return 1
fi
}
# 重载配置
reload() {
check_config || return 1
echo -e "${YELLOW}正在重载Nginx配置...${NC}"
if systemctl reload nginx; then
echo -e "${GREEN}配置重载成功${NC}"
return 0
else
echo -e "${RED}配置重载失败${NC}"
return 1
fi
}
# 显示状态
status() {
systemctl status nginx --no-pager
}
# 显示帮助信息
usage() {
echo "用法: $0 {start|stop|restart|reload|status|check}"
exit 1
}
# 主程序
check_installed
case
