我正在编写一个脚本,使用 bash 脚本检查 mysql 数据库,我想检查表的状态是否不是“OK”,将返回表名并执行更多操作:
检查日志
table1 OK
table2 Some error here
table3 OK
table4 OK
table5 Another error
table6 OK
table7 Broken
table8 A very long error which take a 2 lines
of multiple errors
检查文件
# check and repair tables
mysqlcheck -u $hostUser -p$hostPasswd --all-databases --check --auto-repair >> check.log
# grep tables status, should return OK
cat check.log | grep 'OK' | awk '{print $2}'| while read status; do
# if any table does not contain OK
if [ "$status" != "OK" ]
then
##### HERE WHERE I am stuck
#### It loops and return all the table
# grep to get the table name
cat check.log | grep 'OK' | awk '{print $1}'| while read table; do
echo $tblName' is BROKEN'
done
else
echo $tblName' is FINE'
fi
done
// here I need to mail the tables that have problems in one single mail
寻找类似这样的输出:
tableName: error
tableName: error
table2: Some error here
table5: Another error
and so on
这些行将输出到日志文件(result.txt)
感谢您的支持
答案1
您不需要使用 bash 逐行读取文件。Awk 已经做到了这一点。例如,您可以使用此代码打印损坏的条目
awk '$2!="OK"{print $0}' check.log
您还可以只打印表名并使用该命令创建一个数组,然后对其执行操作:
array=( $(awk '$2!="OK"{printf "%s ",$1 }' check.log) )
请注意旁边的空格%s
,这很重要。
您还提到,错误可以是多行的,就像 table8 一样。我们可能想避免这种情况。所以我们还可以添加一个检查,检查字段 1 是否包含单词 table。
$> array=( $(awk '$1~/table/ && $2!="OK"{printf "%s ",$1 }' check.log) )
$> echo ${array[@]}
table2 table5 table7 table8
$> echo ${array[0]}
table2
答案2
由于awk
的默认行为是在 True 条件发生时打印整行,因此您可以简单地这样说:
awk '$NF != "OK"' file
根据给定的输入返回以下内容:
table2 Some error here
table5 Another error
table7 Broken
table8 A very long error which take a 2 lines
of multiple errors
解释
NF
代表字段数,so$NF
代表字段号NF
。即每行的最后一个字段。- 假设
$NF != "OK"
我们正在检查行上的最后一个字段是否为“OK
”。如果不是,则条件为真,并自动打印该行。