我想用关键字 ALARM/FATAL 过滤我的日志文件到另一个备份文件中,假设我有以下两个文件
[root@TENCENT64 /tmp/test]# cat test_ccd.log
ccd0.log:01-28 09:33:18:461 1254 F NORMAL
ccd0.log:01-28 09:33:18:461 1254 F FATAL
ccd0.log:01-28 09:34:30:827 1254 E ALARM
[root@TENCENT64 /tmp/test]# cat test_mcd.log
mcd0.log:01-29 09:33:18:461 1254 F NORMAL
mcd0.log:01-29 09:33:18:461 1254 F FATAL
mcd0.log:01-29 09:34:30:827 1254 E ALARM
我想生成以下备份文件
[root@TENCENT64 /tmp/test]# cat test_ccd.log.txt
ccd0.log:01-28 09:33:18:461 1254 F FATAL
ccd0.log:01-28 09:34:30:827 1254 E ALARM
[root@TENCENT64 /tmp/test]# cat test_mcd.log.txt
mcd0.log:01-29 09:33:18:461 1254 F FATAL
mcd0.log:01-29 09:34:30:827 1254 E ALARM
我尝试了以下命令来实现该目的,但它们都没有成功,请有人帮助纠正我做错的任何事情?
[root@TENCENT64 /tmp/test]# cat /etc/redhat-release
CentOS Linux release 7.2 (Final)
# this commands hangs for ever
[root@TENCENT64 /tmp/test]# find . -name "*.log" -type f -exec sh -c 'grep -E "ALARM|FATA:" 1>>"$0.txt"' {} \;
# this commands reports the error and the output was missed up
[root@TENCENT64 /tmp/test]# find . -name "*.log" -type f -exec sh -c 'grep -R -E "ALARM|FATA:" 1>>"$0.txt"' {} \;
grep: input file ‘test_mcd.log.txt’ is also the output
grep: input file ‘test_ccd.log.txt’ is also the output
# the output for each file is not correct
[root@TENCENT64 /tmp/test]# cat test_mcd.log.txt
test_mcd.log:mcd0.log:01-29 09:34:30:827 1254 E ALARM
test_ccd.log:ccd0.log:01-28 09:34:30:827 1254 E ALARM
[root@TENCENT64 /tmp/test]# cat test_ccd.log.txt
test_mcd.log:mcd0.log:01-29 09:34:30:827 1254 E ALARM
test_ccd.log:ccd0.log:01-28 09:34:30:827 1254 E ALARM
test_mcd.log.txt:test_mcd.log:mcd0.log:01-29 09:34:30:827 1254 E ALARM
test_mcd.log.txt:test_ccd.log:ccd0.log:01-28 09:34:30:827 1254 E ALARM
当我尝试使用以下代码将备份警报保存到另一个位置时,事情也变得复杂,我有一个 NFS 共享来存储备份警报,并且每个警报都单独存储到共享上的文件夹(以 IP 地址命名)中,下面是我的命令
# create the backed folder on the NFS share, like /data/backup/1.1.1.1/alarm_history
ip=`hostname -I|awk '{print $1}'` && mkdir -p /data/backup/${ip}/alarm_history
# iterate through /data/backup/1.1.1.1 to find all the alarms and persist into /data/backup/1.1.1.1/alarm_history, /data/backup is a shared base and 1.1.1.1 is mounted on the current server
ip=`hostname -I|awk '{print $1}'` && find /data/backup/${ip} -name '*.log' -type f -exec sh -c '
grep -E "ALARM|FATAL" "$1" >> "/data/backup/${ip}/alarm_history/$1.alarm" && sort -o "/data/backup/${ip}/alarm_history/$1.alarm" -u "/data/backup/${ip}/alarm_history/$1.alarm"
' 'find-sh' {} \;
它会产生两个错误:
find-sh: line 1: /data/backup//alarm_history//data/backup/11.62.17.249/manager/manager_mcd0.log.alarm: No such file or directory
find-sh: line 1: /data/backup//alarm_history//data/backup/11.62.17.249/manager/manager_mcd0_stat.log.alarm: No such file or directory
它们是两个问题,1,传递到命令“find”的 ${ip} 无法在 grep 中识别。 2. $1.alarm,$1是grep中的绝对路径,我怎样才能得到它的基本名称?
答案1
grep
缺少参数,:
应该是 anL
以获得预期结果,因此
grep -E "ALARM|FATA:" 1>> "$0.txt"
应该
grep -E "ALARM|FATAL" "$0" > "$0.txt"
(或者如果您想将结果附加到现有文件,请使用>>
or )1>>
由于$0
命令名称和位置参数应该以 开头$1
,因此您可以添加名称并将结果传递$1
给脚本:
find . -name '*.log' -type f -exec sh -c '
grep -E "ALARM|FATAL" "$1" > "$1.txt"
' 'find-sh' {} \;
sh
或者使用尽可能少的调用来循环结果{} +
:
find . -name '*.log' -type f -exec sh -c '
for file; do
grep -E "ALARM|FATAL" "$file" > "${file}.txt"
done
' 'find-sh' {} +
编辑:
我为目标目录添加了一个变量,该变量作为第一个参数传递给脚本。为了能够对生成的日志文件进行排序,我使用了一个临时文件。
ip=$(hostname -I | awk '{ print $1 }')
targetdir="/data/backup/$ip/alarm_history"
mkdir -p "$targetdir"
find "/data/backup/$ip" -name '*.log' -type f -exec sh -c '
targetdir=$1; shift
for file; do
# extract the log filename from the path, append ".alarm", prepend directory
targetfile=${targetdir}/${file##*/}.alarm
grep -E "ALARM|FATAL" "$file" >> "$targetfile" \
&& mv "$targetfile" "${targetfile}.tmp" \
&& sort -o "$targetfile" -u "${targetfile}.tmp" \
&& rm "${targetfile}.tmp"
done
' 'find-sh' "$targetdir" {} +
答案2
for
作为循环这可能会更容易
例如
for file in *.log
do
grep -E -- "ALARM|FATAL" "$file" > "$file.txt"
done