如果我们可以在AWK脚本中使用嵌套的getline,请告知我们:
while ( ("tail -f log" |& getline var0) > 0) {
while ( ("ls" | getline ) > 0) {
}
close("ls")
while ( ("date" | getline ) > 0) {
}
close("date")
}
close("tail -f log")
我们可以利用嵌套getline功能的深度是多少,并且在嵌套getline的任何级别都会有输出数据丢失吗?在实施这种风格时我们应该确定哪些事情?
=============================================== ===================================
UPDATE =================== UPDATE ============== UPDATE =========== ==== UPDATE =======
要求:通过探测QA框和网络服务器/服务日志和系统状态,提供实时统计数据和错误。报告将按以下格式生成:
当地日期和时间|分类|组件|条件
假设 - : AWK脚本的执行速度比shell脚本快,并且还具有使用内置解析和其他功能的优势。
实施: - 主命令循环是command0 =“tail -f -n 0 -s 5 ...........”。此命令将启动无限循环,提取QA框的服务/网络服务器的附加日志。 。请注意-f,-s和-n选项,它们将所有附加数据转储到日志中,在每次迭代后休眠5秒钟,然后从现有日志中打印任何默认内容开始。
每次迭代后,捕获并验证系统时间并在10秒间隔后执行各种OS资源命令(每次迭代之间5秒睡眠和处理尾部输出后4秒 - 假设处理所有尾部命令大致取1秒,因此在所有10秒内)
我用于提取OS资源的各种命令是:
I. command1="vmstat | nl | tr -s '\\t '"
II. command2="sar -W 0"
III. command3="top -b -n 1 | nl | tr -s '\\t '"
IV. command4="ls -1 /tmp | grep EXIT"
在脚本中搜索相应的命令(?),然后在脚本中通过while循环来计算相应命令的输出处理。注意我使用'nl'命令进行开发/编码轻松
最终在框中存在/ tmp / EXIT文件会使脚本从框中删除后退出
下面是我的脚本 - 我已经尽可能地添加了自我解释的注释:
#Useage - awk -f script.awk
BEGIN {
command0="tail -f -n 0 -s 5 /x/web/webserver/*/logs/error_log /x/web/webserver/service/*/logs/log"
command1="vmstat | nl | tr -s '\\t '"
command2="sar -W 0"
command3="top -b -n 1 | nl | tr -s '\\t '"
command4="ls -1 /tmp | grep EXIT"
format = "%a %b %e %H:%M:%S %Z %Y"
split("", details)
split("", fields)
split("", data)
split("", values)
start_time=0
printf "\n>%s:\n\n", command0 #dummy print for debuggng command being executed
while ( (command0 |& getline var0) > 0) { #get the command output
if (start_time == 0) #if block to reset the start_time variable
{
start_time = systime() + 4
}
if (var0 ~ /==>.*<==/) { #if block to extract the file name from the tail output - outputted in '==>FileName<==' format
gsub(/[=><]/, "", var0)
len = split(var0, name, "/")
if(len == 7) {file = name[5]} else {file = name[6]}
}
if (len == 7 && var0 ~ /[Ee]rror|[Ee]xception|ORA|[Ff]atal/) { #extract the logs error statements
print strftime(format,systime()) " | Error Log | " file " | Error :" var0
}
if(systime() >= start_time) #check if curernt system time is greater than start_time as computed above
{
start_time = 0 #reset the start_time variable and now execute the system resource command
printf "\n>%s:\n\n", command1
while ( (command1 |& getline) > 0) { #process output of first command
if($1 <= 1)
continue #not needed for processing skip this one
if($1 == 2) #capture the fieds name and skip to next line
{
for (i = 1; i <= NF; i++){fields[$i] = i;}
continue
}
if ($1 == 3) #store the command data output in data array
split($0, data);
print strftime(format,systime()) " | System Resource | System | Time spent running non-kernel code :" data[fields["us"]]
print strftime(format,systime()) " | System Resource | System | Time spent running kernel code :" data[fields["sy"]]
print strftime(format,systime()) " | System Resource | System | Amount of memory swapped in from disk :" data[fields["si"]]
print strftime(format,systime()) " | System Resource | System | Amount of memory swapped to disk :" data[fields["so"]]
}
close(command1)
printf "\n>%s:\n\n", command2 #start processing second command
while ( (command2 |& getline) > 0) {
if ($4 ~ /[0-9]+[\.][0-9]+/) #check for 4th positional value if its format is of "int.intint" format
{
if( $4 > 0.0) #dummy check now to print if page swapping
print strftime(format,systime()) " | System Resource | Disk | Page rate is > 0.0 reads/second: " $4
}
}
close(command2)
printf "\n>%s:\n\n", command3 # start processing command number 3
while ( (command3 |& getline ) > 0) {
if($1 == 1 && $0 ~ /load average:/) #get the load average from the output if this is the first line
{
split($0, arr, ",")
print strftime(format,systime())" | System Resource | System |" arr[4]
}
if($1 > 7 && $1 <= 12) # print first top 5 process that are consuming most of the CPUs time
{
f=split($0, arr, " ")
if(f == 13)
print strftime(format,systime())" | System Resource | System | CPU% "arr[10]" Process No: "arr[1] - 7" Name: "arr[13]
}
}
close(command3)
printf "\n>%s:\n\n", command4 #process command number 4 to check presence of file
while ( (command4 |& getline var4) > 0) {
system("rm -rf /tmp/EXIT")
exit 0 #if file is there then remove the file and exit this script execution
}
close(command4)
}
}
close(command0)
}
输出 - :
>tail -f -n 0 -s 5 /x/web/webserver/*/logs/error_log /x/web/webserver/service/*/logs/log:
>vmstat | nl | tr -s '\t ':
Sun Dec 16 23:05:12 PST 2012 | System Resource | System | Time spent running non-kernel code :9
Sun Dec 16 23:05:12 PST 2012 | System Resource | System | Time spent running kernel code :9
Sun Dec 16 23:05:12 PST 2012 | System Resource | System | Amount of memory swapped in from disk :0
Sun Dec 16 23:05:12 PST 2012 | System Resource | System | Amount of memory swapped to disk :2
>sar -W 0:
Sun Dec 16 23:05:12 PST 2012 | System Resource | Disk | Page rate is > 0.0 reads/second: 3.89
>top -b -n 1 | nl | tr -s '\t ':
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | load average: 3.63
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 12.0 Process No: 1 Name: occworker
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 10.3 Process No: 2 Name: occworker
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 6.9 Process No: 3 Name: caldaemon
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 6.9 Process No: 4 Name: occmux
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 6.9 Process No: 5 Name: top
>ls -1 /tmp | grep EXIT:
答案 0 :(得分:6)
这是你回忆起关于以这种方式使用getline的第二篇文章。我上次提到这是错误的方法,但看起来你不相信我,所以让我再试一次。
您的问题“我如何使用awk执行带getline的命令来读取输出?”就像问“我如何使用钻头切割玻璃?”。你可以得到一个答案,告诉你把你要钻的玻璃部分贴在上面,以避免它破裂,这样可以回答你的问题,但更有用的答案可能就是 - 不要这样做,不要用玻璃刀
使用awk作为从中调用命令的shell是100%错误的方法。只需使用合适的工具即可完成正确的工作。如果需要解析文本文件,请使用awk。如果您需要操作文件或进程或调用命令,请使用shell(或等效的OS)。
最后,请阅读http://awk.freeshell.org/AllAboutGetline,在完全理解所有注意事项之前,请不要考虑使用getline。
编辑:这是一个shell脚本来执行你发布的awk脚本所做的事情:
tail -f log |
while IFS= read -r var0; do
ls
date
done
看起来更简单?不是说这样做是有意义的,但是如果你确实想要这样做,那就是实现它的方式,而不是awk。
编辑:这里是如何在shell中编写你的awk脚本的第一部分(在这种情况下是bash),我没有热情为你翻译剩下的部分,我想这会告诉你如何自己做其余的事情:format = "%a %b %e %H:%M:%S %Z %Y"
start_time=0
tail -f -n 0 -s 5 /x/web/webserver/*/logs/error_log /x/web/webserver/service/*/logs/log |
while IFS= read -r line; do
systime=$(date +"%s")
#block to reset the start_time variable
if ((start_time == 0)); then
start_time=(( systime + 4 ))
fi
#block to extract the file name from the tail output - outputted in '==>FileName<==' format
case $var0 in
"==>"*"<==" )
path="${var0%% <==}"
path="${path##==> }"
name=( ${path//\// } )
len="${#name[@]}"
if ((len == 7)); then
file=name[4]
else
file=name[5]
fi
;;
esac
if ((len == 7)); then
case $var0 in
[Ee]rror|[Ee]xception|ORA|[Ff]atal ) #extract the logs error statements
printf "%s | Error Log | %s | Error :%s\n" "$(date +"$format")" "$file" "$var0"
;;
esac
fi
#check if curernt system time is greater than start_time as computed above
if (( systime >= start_time )); then
start_time=0 #reset the start_time variable and now execute the system resource command
....
请注意,这会比你的awk脚本执行得稍快,但这完全没关系,因为你的尾巴在迭代之间需要5秒钟的休息时间。
另请注意,我上面所做的就是将你的awk脚本翻译成shell,这并不一定意味着它是从头开始编写这个工具的最好方法。