at执行复杂脚本需用<< 'EOF'内联封装自包含脚本体,首行#!/bin/bash,启用set -e -u -o pipefail,分层校验目录与状态,绝对路径,显式重定向日志,并通过sudo -u指定用户安全提交。
在 at 中直接执行含多级目录判定、多状态校验的复杂 Shell 脚本,不能靠简单命令拼接 —— EOF 本身不是“打包机制”,而是 Bash 的 here-document 语法,用于将多行内容(含变量、缩进、换行)原样传递给命令或写入文件。真正实现“无缝打包+安全提交”的关键是:把完整逻辑封装为自包含、无依赖、可验证的脚本片段,再通过 at 执行该片段。
不要在 at 命令里写一堆 if 和 test;而是用 cat << 'EOF' | at 或重定向到临时文件再 at -f。关键点:
<< 'EOF'(单引号包裹)禁止变量展开和命令替换,确保脚本体字面量安全传递$PWD)#!/bin/bash 并用 set -e -u -o pipefail 强制失败中断与未定义变量报错目录判定不是简单 test -d,要分层、带重试、有回退。例如:
mkdir -p /opt/app/{config,logs,data},再逐级 stat -c "%U:%G %a" /opt/app 校验属主与权限if [[ $(find /opt/app/config -maxdepth 0 -type d -printf "ok") ]] && [[ $(ls -A /opt/app/config | wc -l) -ge 2 ]]; then ... fi
wait_for_port() { timeout 30s bash -c 'until nc -z $0 $1; do sleep 2; done' "$1" "$2"; }
at 本身不提供加密或签名,安全靠“内容可信+执行隔离”:
at -f script.sh 比 at << EOF 更易审计;若必须内联,先 sha256sum <(cat << 'EOF' ...) 记录指纹echo "...script..." | sudo -u deploy at now + 1min,避免 root 权限滥用trap 'rm -f /tmp/at_$$*.log' EXIT,防止临时文件残留很多失败源于环境差异:
at 默认使用 /bin/sh,不是 bash —— 所以内联脚本第一行必须是 #!/bin/bash,且用 echo '#!/bin/bashn...' | at now 方式提交~ 或 ./,所有 cd 需显式 cd /opt/app || exit 1
2>&1 > /var/log/deploy_$(date +%s).log,避免日志丢失