如何在 linux bash 脚本中在 "exec &" 生成的输出之前加上 time/Date?

How to preceed the output generated by "exec &" with a time/Date in linux bash scripts?

我有以下脚本文件可将文件从本地文件系统写入 s3:

#!/bin/bash
CURR_DIR=`dirname [=14=]`
SCRIPT_NAME="$(basename [=14=])"
LOG_FILE=$(echo $SCRIPT_NAME | cut -f 1 -d '.')
TODAY=$(date '+%Y-%m-%d')
NOW=$(date -d "$(date +%Y-%m-%d)" +%Y"-"%m"-"%d)
LOG_PATH="$CURR_DIR"/logs/"$LOG_FILE"-$TODAY.log
LOG="[$(date '+%Y-%m-%d %H:%M:%S,%3N')]  INFO {$LOG_FILE} -"
ERROR_LOG="[$(date '+%Y-%m-%d %H:%M:%S,%3N')]  ERROR {$LOG_FILE} -"

BUCKET="s3.bucket.example"

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

exec &>> $LOG_PATH

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

if [ "$(ls -A path/to/folderA/)" ]; then
  FILES="$(ls path/to/folderA/*)"
  for file in $FILES ; do
    echo "$LOG File $file found for sync" >> $LOG_PATH
    echo "$LOG Pushing $file to S3 /Folder..." >> $LOG_PATH
    echo -n "$LOG " ; s3cmd put -c /home/config/.s3cfg "$file" "$S3_PUSH"/
    echo "$LOG Command returned code:" $?
    echo "$LOG Copying $file to local backup..." >> $LOG_PATH
    mv "$file" /path/to/folderA/backup/
    echo "$LOG Command returned code:" $? >> $LOG_PATH
    RCC=$?
    if [ $? -eq 0 ]
    then
        echo "$LOG Command returned code:" $?
    else
        echo "$ERROR_LOG Command returned code:" $?
    fi
  done
else
  echo "$LOG No files found for sync." >> $LOG_PATH
fi

并且输出以特定的 grok 模式出现,我需要将此输出解析为 Elastic Search 中的日志,但是第 27 行输出如下:

[2021-09-02 08:15:25,629]  INFO {TestGrokScriptPattern} - upload: '/path/to/folderA/File.txt' -> 's3://s3.bucket.example/Path/To/Bucket/File.txt'  [1 of 1]
 0 of 0     0% in    0s     0.00 B/s  done

该上传和 0 of 0 0%...行由在第 16 行执行的 exec & 命令创建。

如何让输出不转到下一行前面没有日期、时间和脚本名称,以便不破坏我试图创建的日志模式?

您可以将脚本主体包装在一个块中,然后在一个地方处理整个块的输出,而不是在每一行都重定向输出。然后,您可以使用流编辑器 sed 处理该输出。例如:

if true; then # Always true. Just simplifies redirection.
  echo "Doing something..."
  command_with_output
  command_with_more_output
  echo "Done."
fi | sed "s/^/${LOG}/" > ${LOG_PATH} 2>&1

sed表达式的意思是:用LOG变量的内容替换每行的开头(^)。

在最后使用 2>&1 也消除了对 exec &>> $LOG_PATH 命令的需要。