printf bash 奇怪的行为
printf bash strange behavior
我在 bash 脚本中编写了 2 个日志记录方法:
# Function to log information
function print_info() {
format=""
shift
printf "$(date +'%F %T') ${SCRIPTNAME}: INFO: $format\n" "$@" | tee -a ${LOGFILE};
}
# Function to log error
function print_error() {
format=""
shift
printf "$(date +'%F %T') ${SCRIPTNAME}: ERROR: $format\n" "$@" | tee -a ${LOGFILE} >&2;
}
并将几条消息定义为:
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."
在我的脚本中,我正在使用上述 2 种方法,如下所示:
function tarIt() {
FILE_NAME=
TAR_FILE_NAME=
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
}
我用 2 个文件名调用函数 tarIt
两次,一个存在,另一个不存在,但得到的输出如下所示:
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.
错误字符串没有打印完整。
不明白原因。即使我尝试将方法 print_error 用于其他消息,但它只打印字符串的第一个单词。后面的部分忽略了。
正如@Biffen 在评论中所说,在所有变量引用周围加上双引号。当此命令运行时:
print_error $ERROR_FILE_NOT_EXIST $FILE_NAME
shell 将其扩展为:
print_error File %s is compressed at path %s. /path/to/nonexistent/file
...因此 print_error 函数将 "File" 接收为 $1,将其用作格式字符串,然后得到无意义的输出。顺便说一句,在格式字符串中嵌入数据(日期和脚本名称)也是一个坏主意;使用 %s
并将它们添加到字段部分:
printf "%s %s: INFO: $format\n" "$(date +'%F %T')" "$SCRIPTNAME" "$@" | tee -a "$LOGFILE"
请注意,我还冒昧地双引号引用了 $LOGFILE。请养成将变量引用放在双引号中的习惯,除非有特殊原因不这样做。
我在 bash 脚本中编写了 2 个日志记录方法:
# Function to log information
function print_info() {
format=""
shift
printf "$(date +'%F %T') ${SCRIPTNAME}: INFO: $format\n" "$@" | tee -a ${LOGFILE};
}
# Function to log error
function print_error() {
format=""
shift
printf "$(date +'%F %T') ${SCRIPTNAME}: ERROR: $format\n" "$@" | tee -a ${LOGFILE} >&2;
}
并将几条消息定义为:
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."
在我的脚本中,我正在使用上述 2 种方法,如下所示:
function tarIt() {
FILE_NAME=
TAR_FILE_NAME=
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
}
我用 2 个文件名调用函数 tarIt
两次,一个存在,另一个不存在,但得到的输出如下所示:
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.
错误字符串没有打印完整。
不明白原因。即使我尝试将方法 print_error 用于其他消息,但它只打印字符串的第一个单词。后面的部分忽略了。
正如@Biffen 在评论中所说,在所有变量引用周围加上双引号。当此命令运行时:
print_error $ERROR_FILE_NOT_EXIST $FILE_NAME
shell 将其扩展为:
print_error File %s is compressed at path %s. /path/to/nonexistent/file
...因此 print_error 函数将 "File" 接收为 $1,将其用作格式字符串,然后得到无意义的输出。顺便说一句,在格式字符串中嵌入数据(日期和脚本名称)也是一个坏主意;使用 %s
并将它们添加到字段部分:
printf "%s %s: INFO: $format\n" "$(date +'%F %T')" "$SCRIPTNAME" "$@" | tee -a "$LOGFILE"
请注意,我还冒昧地双引号引用了 $LOGFILE。请养成将变量引用放在双引号中的习惯,除非有特殊原因不这样做。