我们假设我在这种层次结构中有几个文件夹:
/somewhere/firstDirectory
/somewhere/secondDirectory
/somewhere/DifferentOne
/somewhere/ImportantLogs
/somewhere/CFPC
(这里有很多不同的文件夹)
我想编写一个bash脚本,它将解析一定数量目录中的所有文件 在这些层次结构中,由于将部署的环境不同,这可能会有所不同。 脚本应检查的目录,其名称和文件内容可能会有所不同。
因此,我没有创建一个具有大量逻辑分支的通用脚本,而是开始意识到将更好的内容放在一起 进入属性文件,就像这些示例二:
env1.properties:
$LOG_DIR="/somewhere/[firstDirectory,CFPC]"
$MATCHING_PATTERN="ERROR.*"
env2.properties:
$LOG_DIR="/somewhere/[ImportantLogs,DifferentOne,CFPC]"
$MATCHING_PATTERN="ERROR.*((Parsing ERROR with reason)$"
然后我们有一个这样的脚本:
#!/bin/bash
. $CONFIG/common/error_mailer.properties
ENTRY_MAX_AGE=$(($MAX_AGE_IN_HOURS*60*60))
LOG_FILES=$(find $LOG_DIR -type f -name $FILE_PATTERN)
LINES_WITH_ERRORS=$(zegrep -h "$MATCHING_PATTERN" $LOG_FILES | awk -v max_age=$ENTRY_MAX_AGE 'BEGIN {FS="[:. ]"} {now=systime()} {then=mktime(20$3 " " $2 " " $1 " " $4 " " $5 " " $6); if((now-max_age)<=then) print $0}')
if [ ! -z "$LINES_WITH_ERRORS" ]
then
COUNT=$(echo "$LINES_WITH_ERRORS" | wc -l )
RESULT_TABLE=$(
echo -e "$LINES_WITH_ERRORS" |
sort |
head -n $MAX_NUMBER_OF_ITEMS |
gawk -vpattern="$MATCHING_PATTERN" 'BEGIN{printf "Date and Time\t\tError Item\\n"} match($0, pattern, m){printf $1 " " $2 "\t" m[1] ".\\n"}'
)
MESSAGE+="$COUNT\n\n"
if [ $COUNT -ge $MAX_NUMBER_OF_ITEMS ]
then
MESSAGE+=$MAIL_SUMMARY_TRIM
else
MESSAGE+=$MAIL_SUMMARY
fi
MESSAGE+=$RESULT_TABLE
MESSAGE+=$FOOTER
SUBJECT="$TITLE - $TOTAL_NUMBER_MESSAGE$COUNT"
MESSAGE=$(echo -e "$MESSAGE" | sed 's/$/\r/')
echo -e "Sending message with subject '$SUBJECT' and body:\n$MESSAGE\n"
echo -e "$MESSAGE" | mail -v -s "$SUBJECT" "$RECIPIENT_LIST"
else
echo "Nothing to send"
fi
(TITLE,FOOTER,$ TOTAL_NUMBER_MESSAGE,MAIL_SUMMARY_TRIM对于解释此问题变量并不重要)
我想问一下,如果我尝试做的是正确的吗?或者它应该在bash中以不同的方式完成? 特别是那部分:$ LOG_DIR =“/ somewhere / [firstDirectory,CFPC]”对我来说有点可疑,因为我不知道如何优雅地传递我想要检查的文件夹。我找不到更好的方法 解决这个问题。如果您可以建议我如何提高脚本质量,我将不胜感激。
答案 0 :(得分:1)
你的通配符错了。在使用方括号的地方,你应该使用卷曲的。
但是,因为Bash不会在此上下文中执行大括号扩展,所以我会将变量更改为数组,然后相应地更改调用代码。
此外,您指定的变量不应该有美元符号。 (美元符号用于插值,即访问变量的值。)
LOG_DIRS=( /somewhere/{firstDirectory,CFPC} )
MATCHING_PATTERN="ERROR.*"
然后在您的主脚本中,将$LOG_DIR
更改为"${LOG_DIRS[@]}"
(请注意,我重命名了该变量以更好地反映其内容)。
在grep
及其变体使用的正则表达式中,尾随通配符是无用的;程序在每个输入行的任何位置查找模式。