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

Linux bash脚本如何为exec &>>输出添加日期时间日志前缀

问题解决方法

核心需要解决两个问题:

  1. 你当前定义的LOG/ERROR_LOG变量是脚本启动时就固定了时间戳,所有日志都会用同一个时间,不符合实际输出时间的需求
  2. 第三方命令(s3cmd)的输出没有经过你的前缀处理,直接写入日志导致格式断裂

1. 替换固定日志前缀为动态生成的日志函数

封装通用日志函数,每次调用时动态生成时间戳,同时支持直接传参输出、接收管道输入给每一行加前缀两种场景:

LOG_FILE=$(basename "$0" | cut -f 1 -d '.')
# 定义INFO级别日志函数
log_info() {
    local prefix="[$(date '+%Y-%m-%d %H:%M:%S,%3N')]  INFO {$LOG_FILE} - "
    if [ $# -gt 0 ]; then
        echo "${prefix}$*"
    else
        while IFS= read -r line; do
            echo "${prefix}${line}"
        done
    fi
}
# 定义ERROR级别日志函数
log_error() {
    local prefix="[$(date '+%Y-%m-%d %H:%M:%S,%3N')]  ERROR {$LOG_FILE} - "
    if [ $# -gt 0 ]; then
        echo "${prefix}$*"
    else
        while IFS= read -r line; do
            echo "${prefix}${line}"
        done
    fi
}

2. 修改s3cmd调用逻辑

  • 给s3cmd加--no-progress参数,关闭动态刷新的进度条输出,避免生成无意义的控制字符和碎行
  • 把s3cmd的所有输出(标准输出+错误输出)通过管道传给log_info函数,每一行自动加上统一前缀
# 原s3cmd调用替换为如下写法
s3cmd put --no-progress -c /home/config/.s3cfg "$file" "$S3_PUSH"/ 2>&1 | log_info

3. 其他必要优化(建议保留)

  • 不要用ls遍历文件,直接用glob匹配避免文件名带空格/特殊字符时报错
  • 已经用exec &>> $LOG_PATH做了全局输出重定向,不需要再给每个echo重复指定>> $LOG_PATH
  • 提前创建日志目录避免路径不存在时报错

修改后完整脚本

#!/bin/bash
CURR_DIR=$(dirname "$0")
SCRIPT_NAME="$(basename "$0")"
LOG_FILE=$(echo "$SCRIPT_NAME" | cut -f 1 -d '.')
TODAY=$(date '+%Y-%m-%d')
LOG_PATH="$CURR_DIR"/logs/"$LOG_FILE"-"$TODAY".log
# 提前创建日志目录
mkdir -p "$(dirname "$LOG_PATH")"

# 定义INFO级别日志函数,支持直接传参和管道输入
log_info() {
    local prefix="[$(date '+%Y-%m-%d %H:%M:%S,%3N')]  INFO {$LOG_FILE} - "
    if [ $# -gt 0 ]; then
        echo "${prefix}$*"
    else
        while IFS= read -r line; do
            echo "${prefix}${line}"
        done
    fi
}

# 定义ERROR级别日志函数
log_error() {
    local prefix="[$(date '+%Y-%m-%d %H:%M:%S,%3N')]  ERROR {$LOG_FILE} - "
    if [ $# -gt 0 ]; then
        echo "${prefix}$*"
    else
        while IFS= read -r line; do
            echo "${prefix}${line}"
        done
    fi
}

BUCKET="s3.bucket.example"
OUT_FOLDER="path/to/folderA"
S3_PUSH="s3://$BUCKET/$OUT_FOLDER"

# 全局输出重定向到日志文件
exec &>> "$LOG_PATH"

log_info "Copying files to local out folder..."
cp /path/to/folderA/*.* /path/to/folderB
log_info "Command returned code: $?"

# 用glob判断文件是否存在,避免ls的兼容性问题
shopt -s nullglob
files=(/path/to/folderA/*)
if [ ${#files[@]} -gt 0 ]; then
  for file in "${files[@]}" ; do
    # 跳过目录只处理文件
    [ -f "$file" ] || continue
    log_info "File $file found for sync"
    log_info "Pushing $file to S3 /Folder..."
    # s3cmd所有输出自动加前缀
    s3cmd put --no-progress -c /home/config/.s3cfg "$file" "$S3_PUSH"/ 2>&1 | log_info
    s3_rc=$?
    log_info "s3cmd command returned code: $s3_rc"
    log_info "Copying $file to local backup..."
    mv "$file" /path/to/folderA/backup/
    mv_rc=$?
    log_info "mv command returned code: $mv_rc"
    if [ $mv_rc -ne 0 ]; then
        log_error "Failed to move $file to backup folder, return code: $mv_rc"
    fi
  done
else
  log_info "No files found for sync."
fi

修改后所有s3cmd的输出行都会带上统一的时间、脚本名前缀,完全符合你的grok解析规则,不会再出现无前缀的异常行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 03:36:00