上一篇
linux下脚本文件如何写
- Linux
- 2025-08-06
- 40
在 Linux 中创建脚本文件,首行添加
#!/bin/bash(或其他解释器路径),编写命令后保存为
.sh 文件,通过
chmod +x 赋予
以下是关于 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 &→ 即使关闭终端,任务仍继续运行,输出重定向到文件。
️ 注意:后台任务的标准输出/错误不会自动显示,建议重
