简体   繁体   中英

printf bash strange behavior

I have written 2 logging methods in bash script as:

# Function to log information
function print_info() {
  format="$1"
  shift
    printf "$(date +'%F %T') ${SCRIPTNAME}: INFO: $format\n" "$@" | tee -a ${LOGFILE};
}

# Function to log error
function print_error() {
  format="$1"
  shift
    printf "$(date +'%F %T') ${SCRIPTNAME}: ERROR: $format\n" "$@" | tee -a ${LOGFILE} >&2;
}

And defined few messages as:

BACKUP_DIR_INFO="All the contents of directory %s are compressed to %s."
BACKUP_FILE_INFO="File %s is compressed at path %s."
ERROR_FILE_NOT_EXIST="File or directory %s does not exist."

From my script, I am using the 2 above methods as shown:

function tarIt() {
  FILE_NAME=$1
  TAR_FILE_NAME=$2
  if ! ([ -f $FILE_NAME ] || [ -d $FILE_NAME ]);
  then
    print_error $ERROR_FILE_NOT_EXIST $FILE_NAME
  else
    if [[ -f $FILE_NAME ]]
    then
      print_info "$BACKUP_FILE_INFO" "$FILE_NAME" "$BACKUP_DIR"
    else
      print_info "$BACKUP_DIR_INFO" "$FILE_NAME" "$TAR_FILE_NAME"
    fi
  fi
}

I called the function tarIt twice with 2 file names, out of one exist and another does not exist, but getting the output as shown below:

2015-03-15 09:42:46 : ERROR: File
2015-03-15 09:42:46 : INFO: All the contents of directory /opt/mgtservices/relay/logs are compressed to /root/backup/relay_logs.tar.gz.

The error string is not printing completely.

Not getting the reason. Even I tried to use the method print_error for other messages, but only the first word of string it is printing. Later part it is ignoring.

As @Biffen said in a comment, put double-quotes around all variable references. When this command runs:

print_error $ERROR_FILE_NOT_EXIST $FILE_NAME

The shell expands it to:

print_error File %s is compressed at path %s. /path/to/nonexistent/file

...and the print_error function therefore receives "File" as $1, uses that as the format string, and you get nonsense output. BTW, it's also a bad idea to embed data (the date and script name) in a format string; use %s and add them to the fields section:

printf "%s %s: INFO: $format\n" "$(date +'%F %T')" "$SCRIPTNAME" "$@" | tee -a "$LOGFILE"

Note that I also took the liberty of double-quoting the reference to $LOGFILE. Please get in the habit of put variable references in double-quotes unless there's a specific reason not to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM