I have the following script file that writes files to s3 from a local file system:
#!/bin/bash CURR_DIR=`dirname $0` SCRIPT_NAME="$(basename $0)" 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
And the output is coming out in a specific grok pattern needed for me to parse this output as logs into Elastic Search, however the line 27 output is as follows:
[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
that upload and 0 of 0 0%… Line is created by the exec & command executed on line 16.
How can I get that output to not go to the next line without the date, time and script name preceeding it in order to not break the log pattern I am trying to create?
Advertisement
Answer
Rather than redirect output on each line, you can wrap the body of the script in a single block and then handle the output of the entire block in one place. You can then process that output with the stream editor sed
. For example:
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
The sed
expression means: Substitute (s) the beginning of each line (^) with the contents of the LOG
variable.
Using 2>&1
at the end also eliminates the need for the exec &>> $LOG_PATH
command.