以下是关于 Linux 下脚本文件编写 的完整指南,涵盖从基础到进阶的全流程操作、语法规范及实用技巧:
脚本文件的本质与准备工作
什么是 Linux 脚本?
Linux 脚本本质是由一系列命令构成的文本文件,通过指定的解释器(如 /bin/bash
)逐行执行,其核心优势在于自动化任务、批量操作和可复用性。
特性 | 说明 |
---|---|
跨平台性 | 依赖 Unix/Linux 环境,可在多数类 Unix 系统运行 |
灵活性 | 支持条件判断、循环、函数等结构化编程 |
轻量化 | 无需编译,直接通过解释器执行 |
集成能力 | 可调用系统命令、管道符 、重定向 > /< 实现复杂功能 |
创建脚本文件的基础步骤
# 示例:创建名为 myscript.sh 的脚本 touch myscript.sh # 创建空文件 nano myscript.sh # 编辑内容(推荐新手使用 nano) chmod +x myscript.sh # 添加可执行权限 ./myscript.sh # 执行脚本
⚠️ 关键注意点:
- 文件扩展名无强制要求(
.sh
是约定俗成),但需通过 明确指定解释器。 - 若未添加执行权限(
chmod +x
),需用bash myscript.sh
显式调用解释器。
脚本头部规范:Shebang 的必要性
所有正规脚本的第一行必须是 Shebang(),用于声明解释器路径,常见形式如下:
目标解释器 | Shebang 写法 | 适用场景 |
---|---|---|
Bash | #!/bin/bash |
默认 shell,兼容性最好 |
Dash (POSIX) | #!/bin/sh |
最小化依赖,适配旧系统 |
Zsh | #!/bin/zsh |
仅当用户默认 shell 为 zsh |
Python | #!/usr/bin/python3 |
混合编程时需精确路径 |
❌ 错误示范:省略 Shebang 会导致脚本以不确定的默认 shell 执行,可能引发兼容性问题。
核心语法详解
变量操作
操作类型 | 语法示例 | 说明 |
---|---|---|
定义变量 | name="value" |
双引号内可包含空格和特殊字符 |
读取输入 | read var_name |
等待用户输入并存入变量 |
数组定义 | arr=("item1" "item2") |
支持索引访问:${arr[0]} |
字符串拼接 | echo "Hello ${USER}!" |
花括号 用于变量替换 |
删除变量 | unset var_name |
彻底移除变量定义 |
💡 最佳实践:变量名全大写(如 MAX_COUNT=10
)用于区分环境变量,避免与命令冲突。
条件判断
# 单条件判断 if [ $AGE -gt 18 ]; then echo "Adult" elif [ $AGE -eq 18 ]; then echo "Teenager" else echo "Minor" fi # 多条件组合(逻辑与/或) if [[ ( "$OS" == "Ubuntu" ) && ( "$VERSION" > "20.04" ) ]]; then echo "Supported OS" fi
✅ 关键点:
[ ]
等同于test
命令,[[ ]]
是增强版,支持正则表达式。- 数值比较运算符:
-eq
(等于)、-ne
(不等于)、-gt
(大于)。 - 字符串比较:(完全匹配)、(不等)、
<
/>
(字典序)。
循环结构
循环类型 | 语法模板 | 典型场景 |
---|---|---|
For 循环 | for i in {1..5}; do echo $i; done |
固定次数迭代 |
While 循环 | count=0; while [ $count -lt 5 ]; do echo $count; count=$((count+1)); done |
条件控制循环 |
Until 循环 | until false; do sleep 1; done |
无限循环(需手动终止) |
遍历文件 | for file in .txt; do cat "$file"; done |
批量处理同类文件 |
🔄 嵌套循环示例:打印九九乘法表
for i in {1..9}; do for j in {1..$i}; do printf "%d x %d = %dt" $j $i $(($j $i)) done echo # 换行 done
参数处理
脚本可通过 $n
获取命令行参数($0
是脚本名,$1
~$9
是前九个参数):
#!/bin/bash echo "Total arguments: $#" # 参数总数 echo "All arguments: $@" # 所有参数(带引号) echo "First argument: $1" # 第一个参数 # 移位处理(依次消耗参数) while [ $# -gt 0 ]; do echo "Processing: $1" shift # 左移一位,丢弃第一个参数 done
🔧 高级用法:使用 getopts
解析短选项:
while getopts ":ahv" opt; do case $opt in a) ALGO=fast;; h) HELP=true;; v) VERBOSE=true;; ?) echo "Invalid option: -$OPTARG" >&2; exit 1;; esac done
调试与错误处理
启用调试模式
#!/bin/bash set -euxo pipefail # 推荐组合:显示命令+出错退出+未定义变量报错+管道失败即退出
set -e
:任一命令失败则退出脚本。set -u
:使用未定义变量时报错。set -x
:打印每条执行的命令(调试利器)。pipefail
:管道中任意环节失败则整个管道失败。
自定义错误处理
trap 'echo "Error occurred at line $LINENO"; exit 1' ERR # 当发生错误时触发陷阱,打印行号并退出
实战案例:日志分析脚本
#!/bin/bash # log_analyzer.sh 统计指定日志文件中的错误次数 LOGFILE=${1:-"/var/log/syslog"} # 默认日志路径 ERROR_PATTERN="error|fail|exception" # 正则匹配模式 if [ ! -f "$LOGFILE" ]; then echo "Error: Log file not found!" >&2 exit 1 fi grep -E "$ERROR_PATTERN" "$LOGFILE" | wc -l > error_count.tmp total_errors=$(cat error_count.tmp) rm error_count.tmp echo "Found $total_errors errors in $LOGFILE" exit 0 # 成功退出
📋 执行方式:./log_analyzer.sh /path/to/custom.log
最佳实践清单
类别 | 建议做法 | 原因说明 |
---|---|---|
可移植性 | 始终使用 #!/bin/bash 而非 #!/bin/sh |
sh 可能是 Dash,功能受限 |
安全性 | 对外部输入进行转义:input=$(echo "$user_input" | base64) |
防止命令注入攻击 |
性能优化 | 将频繁调用的命令放入函数,减少磁盘 I/O | 提升重复执行效率 |
日志记录 | 重定向输出到文件:command >> script.log |
便于事后排查问题 |
版本控制 | 将脚本纳入 Git 管理,标注修改日期 | 追踪变更历史 |
相关问答 FAQs
Q1: 为什么我的脚本提示 “Permission denied”?
A: 可能原因及解决方案:
- 缺少执行权限 → 执行
chmod +x script.sh
- Shebang 路径错误 → 确保 后跟的是系统中存在的解释器路径(可用
which bash
查看) - 文件格式问题 → Windows 下创建的文件可能有 CRLF 换行符,用
dos2unix script.sh
转换。
Q2: 如何在脚本中后台运行长时间任务?
A: 两种常用方法:
- & 符号:
long_task &
→ 任务在后台运行,立即返回控制权。 - nohup + &:
nohup long_task > output.log &
→ 即使关闭终端,任务仍继续运行,输出重定向到文件。
⚠️ 注意:后台任务的标准输出/错误不会自动显示,建议重
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/94561.html