我在系统日志中有这个:
Feb 27 02:53:51 Latitude-E6430 rsyslogd: action up 7
Feb 27 02:53:51 Latitude-E6430 rsyslogd: action down B
Feb 27 02:53:51 Latitude-E6430 rsyslogd: action up U
....etc
我想编写一个脚本来全天候监控日志作为服务,但我不知道如何执行该条件。
1-当您逐行读取时,将其存储在变量中。
2 -读取变量如果它在该行中找到单词 [rsyslogd] 和 [7],则显示 [echo "Found" ]
这将是一个循环,逐行读取文件,寻找单词模式。
示例脚本
path_full_log="/home/full.log"
function reader_time_real(){
while read full_log; do
chek7=$(cat $full_log | grep "rsyslogdd" | grep 7 )
if [[ $? = 0 ]]; then
echo "Found 7";
fi
chekB=$(cat $full_log | grep "rsyslogdd" | grep B )
if [[ $? = 0 ]]; then
echo "Found B";
fi
done < $path_full_log
}
答案1
您的脚本不适合执行您想要的操作。它只读取文件一次,但读取完整。如果您循环执行此操作,您将不会只获得新的输出,这将是一场性能噩梦。
此外,你对 的使用毫无用处cat
,你使用grep
一个带有正则表达式模式的固定字符串,并将结果保存在你不再使用的变量中。此外,你不应该使用不带引号的文件名变量。
使用tail -f | grep --line-buffered
:
tail -fn0 "$path_full_log" \
| grep -F --line-buffered 'rsyslogdd' \
| grep -Eo --line-buffered '(7|B)' \
| while read line; do
echo "Found $line"
done
或者使用xargs
:
tail -fn0 "$path_full_log" \
| grep -F --line-buffered 'rsyslogdd' \
| grep -Eo --line-buffered '(7|B)' \
| xargs -I{} echo "Found {}"
tail -fn0
当文件添加新行时,读取新行。grep -F
在该行中搜索固定字符串。--line-buffered
告诉grep
在行进入时读取行,而不是等待输入流的结束(这是默认设置)。grep -Eo
搜索模式ERE
(-E
)(7|B)
并仅输出匹配的字符串 (-o
)。while read line
或者xargs -I{}
获取该输出并在输出上运行您的命令(此处echo
:)。
答案2
我编写了以下脚本,该脚本每秒更新一次,并突出显示任何新的日志条目。它还定义了应显示日志的区域(使用和变量logrows
)logcols
,因此它适用于固定大小的终端窗口(我在 tmux 中使用它)。
您可以修改此脚本以仅突出显示符合特定条件的行,如您所指出的。
#!/bin/bash
# Initial configuration variables
logrows=31
logcols=127
# Local function definition
printnew() {
clear
echo -e "\e[0;30;47m"
hightail=$(tail -n "$logrows" /var/log/syslog | cut -b "1-$logcols")
echo -ne "${hightail}\e[0m"
}
printdif() {
(( newrows = logrows - logdiff ))
clear
normtail=$(tail -n "$logrows" /var/log/syslog | head -n "$newrows" | cut -b "1-$logcols")
echo -n "$normtail"
echo -e "\e[0;30;47m"
hightail=$(tail -n "$logdiff" /var/log/syslog | cut -b "1-$logcols")
echo -ne "${hightail}\e[0m"
}
printold() {
clear
normtail=$(tail -n "$logrows" /var/log/syslog | cut -b "1-$logcols")
echo -n "$normtail"
}
# Loop every second
while true
do
sleep 1 &
# Read log sizes
logsize=$(wc -l /var/log/syslog | cut -d ' ' -f1)
(( logdiff = logsize - presize ))
# If more than $logrows lines are new
if (( logdiff > "$logrows" ))
then
printnew
redraw=1
# If less than $logrows lines but more than 0 lines are new
elif (( logdiff > 0 ))
then
printdif
redraw=1
# If no lines are new
else
if [[ "$redraw" -eq 1 ]]
then
printold
redraw=0
fi
fi
presize="$logsize"
wait # for sleep
done
编写脚本时考虑了三种场景:
- 的全部内容
logrows
都是新的 - 所有内容均已突出显示(printnew
)。 - 日志中的某些行是新的 - 这些行已突出显示(
printdif
)。 - 没有新的日志行 — — 没有任何内容突出显示 (
printold
)。
免责声明:代码可能可以优化,但我通常更关心我的代码是否可读,而不是尽可能地简洁。