bash - awk 退出的意外行为
问题描述
我有下一个代码:
process_mem() {
used=`sed -n -e '/^Cpu(s):/p' $temp_data_file | awk '{print $2}' | sed 's/\%us,//'`
idle=`sed -n -e '/^Cpu(s):/p' $temp_data_file | awk '{print $5}' | sed 's/\%id,//'`
awk -v used=$used \
-v custom_cpu_thres=$custom_cpu_thres \
'{
if(used>custom_cpu_thres){
exit 1
}else{
exit 0
}
}'
return=$?
echo $return
if [[ $return -eq 1 ]]; then
echo $server_name"- High CPU Usage (Used:"$used".Idle:"$idle"). "
out=1
else
echo $server_name"- Normal CPU Usage (Used:"$used".Idle:"$idle"). "
fi
}
while IFS='' read -r line || [[ -n "$line" ]]; do
server_name=`echo $line | awk '{print $1}'`
custom_cpu_thres=`echo $line | awk '{print $3}'`
if [ "$custom_cpu_thres" = "-" ]; then
custom_cpu_thres=$def_cpu_thres
fi
expect -f "$EXPECT_SCRIPT" "$command" >/dev/null 2>&1
result=$?
if [[ $result -eq 0 ]]; then
process_mem
else
echo $server_name"- Error in Expect Script. "
out=1
fi
echo $server_name
done < $conf_file
exit $out
问题是读取 bash 循环应该执行 4 次(每行读取一次)。但是,如果我编写带有退出的 awk 代码,则在第一个循环后读取 bash 循环退出。
为什么会这样?在我看来,awk 代码中的退出代码不应该影响 bash 脚本。
问候。
解决方案
我相信你的说法是错误的。
你说:
问题是读取 bash 循环应该执行 4 次(每行读取一次)。但是,如果我编写带有退出的 awk 代码,则读取 bash 循环在第一个循环之后退出。
我不相信脚本在第一个循环后退出,而是卡在第一个循环中。我发表此声明的原因是您的awk
脚本有缺陷。你写的方式是:
awk -v used=$used -v custom_cpu_thres=$custom_cpu_thres \
'{ if(used>custom_cpu_thres){ exit 1 }
else{ exit 0 } }'
这里的问题是 Awk 没有得到输入文件。如果没有输入文件被 awk 证明,它正在读取stdin
(类似于处理管道或键盘输入)。由于没有信息发送到标准输入(除非您按下了几个键并意外点击Enter),因此脚本不会向前移动,并且 Awk 正在等待输入。
仅当未指定文件操作数,或文件操作数为 '-' ,或 progfile 选项参数为 '-' 时,才应使用标准输入;请参阅输入文件部分。如果 awk 程序不包含任何动作和模式,但它是一个有效的 awk 程序,则不应读取标准输入和任何文件操作数,并且 awk 将退出并返回状态为零。
来源:Awk POSIX 标准
以下 bash 行演示了上述语句:
$ while true; do awk '{print "woot!"; exit }'; done
只有当您按一些键后跟Enter,单词“woot!” 打印在屏幕上!
如何解决您的问题:
使用 awk 解决问题的最简单方法是使用BEGIN
块。该块在读取任何输入行(或stdin
)之前执行。如果您告诉 Awk 在开始块中退出,它将终止 Awk 而不读取任何输入。因此:
awk -v used=$used -v custom_cpu_thres=$custom_cpu_thres \
'BEGIN{ if(used>custom_cpu_thres){ exit 1 }
else{ exit 0 } }'
或更短
awk -v used=$used -v custom_cpu_thres=$custom_cpu_thres \
'BEGIN{ exit (used>custom_cpu_thres) }
但是,在这里,Awk 有点过头了。一个简单的 bash 测试就足够了:
[[ "$used" -le "$custom_cpu_thres" ]]
result=$?
或者
(( used <= custom_cpu_thres ))
result=$?
推荐阅读
- django - Django - Celery - SQS - S3 - 接收消息
- c# - JsonConvert.DeserializeObject 抛出无法加载文件或程序集'System.ComponentModel.Annotations,版本 = 4.3.0.0,文化
- ios - 如何检查 SwiftUI 是否处于预览模式?
- c# - 如何使 Json.Net 序列化字典
保留类型信息? - sql-server - 实体数据库未更新
- javascript - 如何制作谷歌折线图参考元素值而不是静态数字
- reactjs - 标签未显示复选框
- c# - 将新数据添加到 LocalDB 后如何更新组合框
- python - 仅在带有硒的特定“id”中按“类”查找元素
- javascript - 一键切换多个类