逾越基础:Shell脚本高级技巧与错误处置处罚
掌握了Shell脚本的基础后,是时间迈向更高条理——编写健壮、高效且可维护的脚本。
函数与模块化:如何编写可复用的函数
当脚本变得复杂时,重复代码会降低可读性和维护性。函数可以将代码模块化,提高复用性。
定义和调用函数
函数定义无需特别关键字,直接写函数名和代码块:
- #!/bin/bash
- # 定义函数
- say_hello() {
- echo "Hello, $1!"
- }
- # 调用函数
- say_hello "Alice"
- say_hello "Bob"
复制代码 输出:
- Hello, Alice!
- Hello, Bob!
复制代码
- $1 是函数的第一个参数,类似脚本中的命令行参数。
带返回值的函数
Shell函数返回值通常通过全局变量或退出码实现:
- #!/bin/bash
- add_numbers() {
- local SUM=$(( $1 + $2 ))
- echo $SUM # 输出结果
- }
- RESULT=$(add_numbers 3 5)
- echo "3 + 5 = $RESULT"
复制代码 输出:3 + 5 = 8
模块化实践
将常勤奋能封装成函数,并保存到外部文件(如 utils.sh),然后在脚本中引入:
- # utils.sh
- log() {
- echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> /var/log/script.log
- }
复制代码- #!/bin/bash
- source ./utils.sh
- log "脚本开始执行"
- echo "做一些工作..."
- log "脚本结束"
复制代码 通过 source 或 .引入外部文件,实当代码复用。
错误处置处罚:退出码、trap和日记
生产环境的脚本必须能处置处罚错误,制止因非常导致系统混乱。
利用退出码
每个命令执行后都有一个退出码(0 表现成功,非 0 表现失败),可用 $? 检查:
- #!/bin/bash
- ls /nonexistent
- if [ $? -ne 0 ]; then
- echo "错误:目录不存在"
- exit 1 # 非零退出码表示脚本失败
- fi
复制代码
trap捕获信号
trap 命令可捕获中断信号(如Ctrl+C)或脚本退出时的状态:
- #!/bin/bash
- cleanup() {
- echo "脚本被中断,正在清理..."
- # 清理临时文件等
- exit 1
- }
- trap cleanup INT TERM # 捕获中断和终止信号
- echo "运行中,按Ctrl+C测试"
- sleep 100
复制代码 按Ctrl+C后,脚本会执行 cleanup 函数。
记录错误日记
将错误信息记录到日记文件,便于排查题目:
- #!/bin/bash
- LOG_FILE="/var/log/script_errors.log"
- log_error() {
- echo "$(date) - ERROR: $1" >> "$LOG_FILE"
- }
- ls /nonexistent 2>/dev/null || log_error "无法访问目录"
- echo "继续执行..."
复制代码
- 2>/dev/null:屏蔽尺度错误输出。
- ||:前命令失败时执行后命令。
脚本优化:提高性能的最佳实践
高效的脚本不但功能强大,还要运行敏捷且资源占用低。
1. 减少外部命令调用
频仍调用外部命令(如 grep、awk)会增加开销,只管利用Shell内置功能:
- # 低效
- COUNT=$(ls -l | wc -l)
- # 高效
- files=( * )
- COUNT=${#files[@]}
复制代码 2. 并行执行
对于耗时任务,利用配景历程(&)并行运行:
- #!/bin/bash
- task() {
- echo "任务 $1 開始"
- sleep 2
- echo "任務 $1 完成"
- }
- task 1 &
- task 2 &
- wait # 等待所有后台任务完成
复制代码 3. 制止冗余操纵
缓存重复利用的效果:
- #!/bin/bash
- # 每次调用date都重新计算
- for i in {1..3}; do
- echo "$(date) - 循环 $i"
- done
- # 优化:只计算一次
- NOW=$(date)
- for i in {1..3}; do
- echo "$NOW - 循环 $i"
- done
复制代码 实战案例:自动化用户管理
以下是一个完备的用户管理脚本,包含创建、删除用户和权限设置功能。
- #!/bin/bash
- LOG_FILE="/var/log/user_management.log"
- USERNAME=""
- ACTION=""
- # 函数:记录日志
- log() {
- echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
- }
- # 函数:检查用户是否存在
- check_user() {
- if id "$1" &>/dev/null; then
- return 0 # 用户存在
- else
- return 1
- fi
- }
- # 函数:创建用户
- create_user() {
- if check_user "$1"; then
- log "用户 $1 已存在"
- echo "用户 $1 已存在"
- else
- useradd -m "$1" && echo "用户 $1 创建成功" || log "创建用户 $1 失败"
- passwd "$1" # 设置密码
- chmod 700 "/home/$1" # 设置权限
- log "用户 $1 创建并配置完成"
- fi
- }
- # 函数:删除用户
- delete_user() {
- if check_user "$1"; then
- userdel -r "$1" && echo "用户 $1 删除成功" || log "删除用户 $1 失败"
- log "用户 $1 已删除"
- else
- echo "用户 $1 不存在"
- log "尝试删除不存在的用户 $1"
- fi
- }
- # 主逻辑
- if [ $# -ne 2 ]; then
- echo "用法:$0 {create|delete} 用户名"
- exit 1
- fi
- ACTION=$1
- USERNAME=$2
- case $ACTION in
- create) create_user "$USERNAME";;
- delete) delete_user "$USERNAME";;
- *) echo "无效操作:$ACTION"; exit 1;;
- esac
- exit 0
复制代码 利用方法
- 创建用户:./user_manage.sh create testuser
- 删除用户:./user_manage.sh delete testuser
功能亮点
- 模块化:将创建和删除逻辑封装为函数。
- 错误处置处罚:检查用户是否存在,记录失败日记。
- 安全性:设置公道的目次权限。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |