菜鸟科技网

Shell命令编写有哪些实用技巧?

Shell 命令编写是 Linux 和 Unix 系统管理中不可或缺的技能,它通过将多个命令组合、使用控制流结构和函数,实现自动化任务处理,极大提升工作效率,Shell 脚本本质上是包含一系列 Shell 命令的文本文件,通过解释器逐行执行,能够完成文件操作、系统监控、数据处理等多种复杂任务,本文将从基础语法、高级特性、实战案例等方面,详细解析 Shell 命令编写的核心要点。

Shell命令编写有哪些实用技巧?-图1
(图片来源网络,侵删)

Shell 脚本基础与语法规范

编写 Shell 脚本首先需要选择解释器,常见的有 Bash(默认)、Sh、Zsh 等,脚本文件通常以 .sh 为后缀,首行需指定解释器,#!/bin/bash(称为 Shebang 行),脚本执行需赋予可读权限,可通过 chmod +x script.sh 实现,然后通过 ./script.shbash script.sh 运行。

变量定义与使用是 Shell 编程的基础,变量无需声明类型,直接通过 name="value" 定义,使用时需加 符号,如 echo $name,变量区分大小写,且默认以字符串形式存储,若需进行算术运算,需借助 expr、 或 let 命令,sum=$((a + b)),Shell 提供特殊变量,如 $0(脚本名)、$1-$9(位置参数)、(参数个数)、(上一条命令的退出状态)、(当前进程 ID)等,这些变量在参数传递和流程控制中至关重要。

输入输出重定向管道是 Shell 命令的核心特性,输入重定向(<)将文件内容作为命令输入,如 sort < numbers.txt;输出重定向(>)覆盖文件内容,>> 追加内容到文件;错误重定向(2>)可将命令错误信息单独输出,ls /nonexistent 2> error.log,管道()则将前一个命令的输出作为后一个命令的输入,如 ps aux | grep nginx 可筛选包含 nginx 的进程。

控制流与条件判断

Shell 脚本通过条件判断循环结构实现逻辑控制。if 语句是最基础的条件分支,格式为:

Shell命令编写有哪些实用技巧?-图2
(图片来源网络,侵删)
if [ condition ]; then
    commands
elif [ condition ]; then
    commands
else
    commands
fi

条件判断需使用 test 命令或 [ ](注意 [] 需空格分隔),常见条件包括:文件操作(-e 文件存在、-f 普通文件、-d 目录)、字符串比较( 等于、 不等于、-z 空字符串)、数值比较(-eq 等于、-ne 不等于、-gt 大于),判断文件是否存在:

if [ -e "/etc/passwd" ]; then
    echo "文件存在"
fi

循环结构中,for 循环常用于遍历列表或文件,格式为:

for item in list; do
    commands
done

遍历当前目录下的所有 .txt 文件:

for file in *.txt; do
    echo "处理文件: $file"
done

while 循环则适用于条件驱动的循环,格式为:

Shell命令编写有哪些实用技巧?-图3
(图片来源网络,侵删)
while [ condition ]; do
    commands
done

每隔 5 秒监控 CPU 使用率,直到超过 80%:

while [ $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1) -lt 80 ]; do
    echo "CPU 使用率正常"
    sleep 5
done
echo "CPU 使用率过高!"

函数与模块化设计

函数可将重复代码封装,提高脚本复用性,定义格式为:

function func_name() {
    commands
    return value  # 返回值仅限 0-255,通常通过 $? 获取
}

调用函数直接写函数名,如 func_name,函数内部可通过 $12 等获取参数,通过 local 定义局部变量避免全局污染,封装一个日志函数:

log() {
    local level=$1
    shift
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*" >> /var/log/app.log
}
log "INFO" "服务启动成功"
log "ERROR" "连接数据库失败"

实战案例:自动化备份脚本

以下是一个自动备份指定目录并保留最近 7 天备份的脚本,综合运用了变量、条件判断、循环和函数:

#!/bin/bash
# 配置参数
SOURCE_DIR="/var/www/html"
BACKUP_DIR="/backup/website"
DATE=$(date +%Y%m%d)
RETENTION_DAYS=7
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 备份函数
backup() {
    local backup_file="$BACKUP_DIR/backup_$DATE.tar.gz"
    tar -czf "$backup_file" "$SOURCE_DIR" 2>/dev/null
    if [ $? -eq 0 ]; then
        log "INFO" "备份成功: $backup_file"
    else
        log "ERROR" "备份失败"
        exit 1
    fi
}
# 清理旧备份函数
cleanup_old_backups() {
    find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +$RETENTION_DAYS -exec rm {} \;
    log "INFO" "已清理 $RETENTION_DAYS 天前的备份"
}
# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$BACKUP_DIR/backup.log"
}
# 主逻辑
backup
cleanup_old_backups
log "INFO" "备份任务完成"

脚本执行流程:首先创建备份目录,调用 backup 函数压缩源目录并记录日志,再通过 find 命令删除超过 7 天的旧备份,最后输出任务完成日志。

常见问题与调试技巧

编写 Shell 脚本时,常见错误包括语法错误(如缺少空格、括号不匹配)、逻辑错误(如条件判断失效)、命令执行失败(如文件路径错误),调试时可采用以下方法:

  1. 开启调试模式:在脚本首行后添加 set -x,会显示每条命令的执行过程;
  2. 检查退出状态:通过 判断上一条命令是否成功,关键命令后可添加 || exit 1
  3. 分步测试:将复杂脚本拆分为小段,逐段验证功能。

相关问答 FAQs

*问题 1:Shell 脚本中 、`$$@的区别是什么?** 解答:$#表示脚本参数的个数,例如./script.sh arg1 arg2$#为 2;$将所有参数视为一个整体(用空格分隔),如"$"输出为"arg1 arg2"$@将每个参数视为独立字符串,如"$@"输出为"arg1" "arg2",在循环中,for arg in "$@"会逐个处理参数,而for arg in "$*"` 会将所有参数作为一个字符串处理。

问题 2:如何在 Shell 脚本中实现多进程并行执行?
解答:可通过 & 将命令放入后台执行,结合 wait 等待所有进程完成。

task1() { sleep 3; echo "任务1完成"; }
task2() { sleep 2; echo "任务2完成"; }
task1 &  # 任务1后台执行
task2 &  # 任务2后台执行
wait     # 等待所有后台任务完成
echo "所有任务完成"

此脚本会并行执行 task1task2,总耗时约 3 秒(取最长任务时间),显著提升效率。

分享:
扫描分享到社交APP
上一篇
下一篇