You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本中日志与错误处理功能的正确配置方法

报错根因
  • 命令替换的反引号配对/边界错误:直接在exec重定向行内写反引号包裹的date命令时,很容易出现边界错位,shell解析到行尾都找不到闭合的反引号,直接抛出匹配反引号失败的EOF错误
  • 原date格式包含空格、冒号等特殊字符:%T输出的时分秒带冒号,日期和时间之间有空格,未加引号包裹的情况下,shell会把空格后的内容识别为独立参数,即使反引号配对正确也会触发执行错误
  • 原exec仅重定向标准输出,执行报错信息不会写入日志,后续排查问题无据可依
功能实现方案

1. 日期后缀日志配置

  • 提前单独定义日志路径变量,不在exec行内直接嵌套命令替换,彻底规避反引号转义问题
  • 日期格式选用文件名兼容的格式:每日定时任务用%Y%m%d(年月日)作为后缀即可实现按天拆分日志不覆盖;如需区分单日多次执行,可精确到秒,用下划线替换空格、横杠替换冒号避免特殊字符解析问题
  • exec同时重定向标准输出、标准错误到日志文件,所有执行trace、报错信息全量落盘
  • 执行前自动创建日志目录,避免路径不存在导致重定向失败

2. SFTP失败邮件告警

  • 逐环节捕获操作返回值:cd目录、cp备份、sftp传输任意环节失败,立刻触发告警,跳过后续无效操作,避免误删本地文件
  • 告警邮件包含核心排查信息:失败时间、操作用户、对应ID、日志路径,收到告警可直接定位问题
  • 仅当sftp传输确认成功后,再删除本地txt文件,避免文件丢失

修复后可直接使用的完整脚本:

#!/bin/bash
# 配置项
LOG_DIR="/root/logs"
CSV_PATH="/绝对路径/us_craig.csv" # 替换为csv文件的绝对路径,避免定时任务工作目录不对找不到文件
ALERT_MAIL="你的告警接收邮箱@xxx.com"
SFTP_KEY="/root/.ssh/id_rsa"
SFTP_TARGET="user@site.domain.com:/home/folder"

# 初始化日志:按天生成日志文件,不会覆盖历史
mkdir -p "$LOG_DIR"
LOG_DATE=$(date '+%Y%m%d') # 精确到秒可改为'+%Y%m%d_%H-%M-%S'
LOG_FILE="${LOG_DIR}/sftp_transfer_${LOG_DATE}.log"
exec > "$LOG_FILE" 2>&1

set -x
echo "=== SFTP传输任务开始执行,时间:$(date '+%Y-%m-%d %H:%M:%S') ==="

while IFS="," read -r col1 col2
do
    echo "=== 开始处理用户:$col1,对应ID:$col2 ==="
    TARGET_DIR="/efs/$col1/ftpout"
    BACKUP_DIR="/efs/$col1/backup"

    # 校验工作目录存在
    if [ ! -d "$TARGET_DIR" ]; then
        echo "错误:用户$col1 的ftpout目录不存在,跳过"
        # 发送告警邮件
        {
        echo "From: SFTP任务告警 <sftp-alert@localhost>"
        echo "To: 运维负责人 <${ALERT_MAIL}>"
        echo "Subject: 【严重】SFTP传输失败 - 用户${col1}"
        echo ""
        echo "SFTP任务执行失败,详情:"
        echo "用户:$col1"
        echo "ID:$col2"
        echo "失败原因:工作目录$TARGET_DIR 不存在"
        echo "失败时间:$(date '+%Y-%m-%d %H:%M:%S')"
        echo "日志路径:$LOG_FILE"
        } | sendmail -t
        continue
    fi

    # 切换目录
    cd "$TARGET_DIR" || {
        echo "错误:切换到目录$TARGET_DIR 失败,跳过"
        {
        echo "From: SFTP任务告警 <sftp-alert@localhost>"
        echo "To: 运维负责人 <${ALERT_MAIL}>"
        echo "Subject: 【严重】SFTP传输失败 - 用户${col1}"
        echo ""
        echo "SFTP任务执行失败,详情:"
        echo "用户:$col1"
        echo "ID:$col2"
        echo "失败原因:切换到工作目录$TARGET_DIR 失败"
        echo "失败时间:$(date '+%Y-%m-%d %H:%M:%S')"
        echo "日志路径:$LOG_FILE"
        } | sendmail -t
        continue
    }

    # 创建备份目录
    mkdir -p "$BACKUP_DIR"
    # 备份文件
    cp * "$BACKUP_DIR" || {
        echo "错误:备份文件到$BACKUP_DIR 失败,跳过"
        {
        echo "From: SFTP任务告警 <sftp-alert@localhost>"
        echo "To: 运维负责人 <${ALERT_MAIL}>"
        echo "Subject: 【严重】SFTP传输失败 - 用户${col1}"
        echo ""
        echo "SFTP任务执行失败,详情:"
        echo "用户:$col1"
        echo "ID:$col2"
        echo "失败原因:文件备份到$BACKUP_DIR 失败"
        echo "失败时间:$(date '+%Y-%m-%d %H:%M:%S')"
        echo "日志路径:$LOG_FILE"
        } | sendmail -t
        continue
    }

    # 执行SFTP传输
    sftp -oIdentityfile="$SFTP_KEY" "$SFTP_TARGET" <<EOF
        put *.txt
        exit
EOF
    SFTP_EXIT_CODE=$?
    if [ $SFTP_EXIT_CODE -ne 0 ]; then
        echo "错误:SFTP传输失败,返回码:$SFTP_EXIT_CODE"
        {
        echo "From: SFTP任务告警 <sftp-alert@localhost>"
        echo "To: 运维负责人 <${ALERT_MAIL}>"
        echo "Subject: 【严重】SFTP传输失败 - 用户${col1}"
        echo ""
        echo "SFTP任务执行失败,详情:"
        echo "用户:$col1"
        echo "ID:$col2"
        echo "失败原因:SFTP文件传输失败,返回码$SFTP_EXIT_CODE"
        echo "失败时间:$(date '+%Y-%m-%d %H:%M:%S')"
        echo "日志路径:$LOG_FILE"
        } | sendmail -t
        continue
    fi

    # 传输成功才删除本地文件
    rm *.txt
    echo "=== 用户$col1 处理完成 ==="

done < <(tail -n +2 "$CSV_PATH")

echo "=== SFTP传输任务全部执行完成,时间:$(date '+%Y-%m-%d %H:%M:%S') ==="

注意:使用前请先确认服务器sendmail服务已正常启动并配置好邮件路由,可先手动执行echo "test" | mail -s "test" 你的邮箱验证邮件发送能力。


内容的提问来源于stack exchange,提问作者Craig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:36:37