You need to enable JavaScript to run this app.
文档中心
大数据研发治理套件

大数据研发治理套件

复制全文
下载 pdf
数据开发
Shell 脚本被终止时如何清理资源
复制全文
下载 pdf
Shell 脚本被终止时如何清理资源

问题说明

Shell 脚本运行过程中可能创建临时文件、锁文件、后台进程或外部资源。如果脚本被手动终止或异常退出,这些资源可能残留。处理思路是:把清理逻辑统一写进 cleanup 函数,并通过 trap 在脚本退出时执行。

处理方法

建议使用 trap 'cleanup' EXIT 作为统一清理入口。需要在收到 TERM、INT、HUP 时做额外处理的,可以单独捕获信号,然后退出脚本,让 EXIT trap 执行清理。
下面是通用骨架,已包含临时目录和后台进程的清理示例;若脚本创建了其他资源(如锁文件、挂载点、远端资源等),请在 cleanup 中补齐相应清理逻辑。

#!/usr/bin/env bash
set -euo pipefail

TMP_DIR=""
CHILD_PID=""

cleanup() {
  # 清理过程失败时,不要影响后续清理
  set +e

  # 终止后台子进程
  if [[ -n "${CHILD_PID}" ]]; then
    kill -TERM "${CHILD_PID}" 2>/dev/null || true
  fi

  # 删除脚本创建的临时目录
  if [[ -n "${TMP_DIR}" && -d "${TMP_DIR}" ]]; then
    rm -rf -- "${TMP_DIR}" || true
  fi
}

on_signal() {
  local sig="$1"
  echo "received ${sig}, exiting..." >&2
  exit 1
}

# 脚本退出时统一清理
trap 'cleanup' EXIT

# 可选:收到终止信号后退出,触发 EXIT 清理
trap 'on_signal TERM' TERM
trap 'on_signal INT'  INT
trap 'on_signal HUP'  HUP

# 创建资源后及时记录
TMP_DIR="$(mktemp -d /tmp/myjob.XXXXXX)"

# 示例:启动后台任务
# long_running_task &
# CHILD_PID=$!

# ...业务逻辑...

注意事项与排查

编写时的注意事项

  • 清理函数要幂等:即使执行多次,也不应误删资源或导致脚本异常。
  • 只清理脚本自己创建的资源:创建成功后立即把路径、进程 ID(PID)、外部资源 ID 保存到变量里,cleanup 通过这些变量删除;删除前检查变量是否为空、路径是否符合预期,避免误删共享目录或他人资源。
  • trap 要尽早注册:在创建资源之前定义 cleanup 并设置 trap,否则注册之前发生的错误无法触发清理。
  • 不要重复 trap 同一个信号:后续代码再次 trap 会覆盖之前的清理逻辑,建议只在脚本开头统一注册一次。
  • 信号处理后要显式退出:捕获 TERM/INT/HUP 后如果不调用 exit,信号相当于被“消化”,脚本会继续运行,收到信号本该触发的清理也不会立即发生。

trap 没生效时怎么排查

  • 确认是否使用了 kill -9。该信号无法捕获,属于预期外场景。
  • 确认信号是否发给了实际执行脚本的进程。脚本被外部封装或作为子进程运行时,真正的 PID 可能不是您以为的那一个。
  • 确认业务是否运行在子 Shell / 子进程中。子进程需要各自注册 trap,或由父进程做信号转发。

无法清理的情况与建议做法

资源无法清理的情况主要有以下两种:

  • 当脚本被非正常终止时,例如 kill -9、机器意外重启或断电、进程被系统强制回收等,清理逻辑没有机会执行。
  • 脚本写到外部存储的残留资源,即便进程内清理能跑,也不会被自动回收。

建议做法:对外部资源额外提供兜底清理机制,例如定期运行清理脚本,或在必要时进行人工清理。如果条件允许,可给外部资源设置统一命名或标签,并配置 TTL,方便定期清理脚本按规则回收。

最近更新时间:2026.09.03 17:37:45
这个页面对您有帮助吗?
有用
有用
无用
无用