Linux 脚本最佳实践

本文最后更新于:2025年7月12日 下午

前文

可以直接把这篇文章喂给 AI, 可以放到 AI 角色设定里,也可以直接作为提示词.
这样,你只管提需求,写脚本就让 AI 来.

一、基础原则

  1. 明确用途

    • 脚本开头用注释说明功能、作者、版本和修改记录

    • 示例:

      1
      2
      3
      4
      #!/bin/bash
      # Purpose: Backup MySQL databases
      # Author: John Doe
      # Version: 1.2 (2023-08-20)
  2. 选择合适的解释器

    • 显式指定解释器(避免依赖默认 shell):

      1
      2
      3
      #!/usr/bin/env bash  # 推荐(兼容性更好)
      # 或
      #!/bin/bash # 明确版本

二、代码规范

  1. 变量管理

    • 命名全大写 + 下划线,局部变量用小写

      1
      2
      readonly CONFIG_FILE="/etc/app.conf"
      local temp_file="$(mktemp)"
    • 引用变量加双引号(防止空格 / 特殊字符问题):

      1
      cp "$source" "$dest"
  2. 错误处理

    • 启用严格模式(脚本开头添加):

      1
      set -euo pipefail  # -e: 错误退出 -u: 未定义变量报错 -o pipefail: 管道错误检测
    • 关键操作检查返回值:

      1
      2
      3
      4
      if ! mkdir "/backup"; then
      echo "Failed to create directory" >&2
      exit 1
      fi
  3. 函数使用

    • 功能模块化,限制函数作用域:

      1
      2
      3
      4
      process_data() {
      local input_file=$1
      # 函数逻辑。..
      }

三、安全性

  1. 输入验证

    • 检查用户输入 / 参数:

      1
      2
      3
      4
      if [[ $# -lt 2 ]]; then
      echo "Usage: $0 <source> <dest>" >&2
      exit 1
      fi
  2. 权限控制

    • 避免使用 root 执行非必要操作:

      1
      2
      3
      4
      if [[ $(id -u) -ne 0 ]]; then
      echo "Requires root privileges" >&2
      exit 1
      fi
  3. 敏感信息

    • 密码 / 密钥等不要硬编码,使用环境变量或配置文件(权限设为 600)

四、可维护性

  1. 日志记录

    • 重要操作输出日志:

      1
      2
      3
      4
      log() {
      echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "/var/log/script.log"
      }
      log "Starting backup process..."
  2. 配置文件分离

    • 将配置参数提取到单独文件(如 config.cfg):

      1
      source ./config.cfg || exit 1

五、调试与测试

  1. 调试模式

    • 运行时显示命令执行:

      1
      2
      3
      bash -x script.sh
      # 或在脚本内启用
      set -x
  2. 单元测试

    • 为关键函数编写测试用例(可使用 bats 框架)

六、性能优化

  1. 减少子进程调用(如避免循环内调用 grep/awk

  2. 使用内置字符串操作替代外部命令:

    1
    2
    # 替代:echo "$str" | cut -d':' -f2
    echo "${str#*:}"
  3. 大文件处理时使用流式处理(避免全量加载到内存)

模板示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env bash
set -euo pipefail

# --- 配置区 ---
readonly LOCK_FILE="/var/lock/script.lock"
readonly LOG_FILE="/var/log/script.log"

# --- 函数区 ---
init() {
if [ -f "$LOCK_FILE" ]; then
log "Error: Script is already running"
exit 1
fi
touch "$LOCK_FILE"
}

cleanup() {
rm -f "$LOCK_FILE"
log "Script completed"
}

log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

# --- 主逻辑 ---
main() {
init
trap cleanup EXIT # 确保退出时清理

# 业务逻辑。..
log "Processing started"
}

main "$@"

Linux 脚本最佳实践
https://ewhisper.cn/posts/48106/
作者
东风微鸣
发布于
2025年7月12日
许可协议