bash,如果十进制更大则工作奇怪

gen*_*bee 2 bash

我有这个脚本来比较cpuload是大于限制10

#!/bin/bash

cpuload=$(uptime | cut -d' ' -f 13 | sed '$ s/.$//')
limit=10

echo
echo "cpuload = $cpuload, limit = $limit"
echo

[[ $cpuload > $limit ]] && echo | mail -s "cpuload $cpuload is higher than $limit!" EMAIL
Run Code Online (Sandbox Code Playgroud)

现在,即使 value 低于 limit ,我也会收到电子邮件(3 > 10)

问题出在哪儿?

我尝试了与条件语法的组合,但有时它起作用,有时不起作用......我有点困惑。

谢谢。

更新

cpu_load=$(uptime | cut -d' ' -f 13 | sed '$ s/.$//')
limit=1

send_email(){
echo | mail -s "makroczsk, cpuload $cpu_load is higher than limit $limit!" $email_to
}

echo "cpuload = $cpu_load (${cpu_load%%.*}), limit = $limit"

[[ (( ${cpu_load%%.*} > $limit )) ]] && send_email
[[ ${cpu_load%%.*} -gt $limit ]] && send_email
Run Code Online (Sandbox Code Playgroud)
cpuload = 3.10, limit = 10
./check-cpuload.sh: line 9: [[: 3.10: syntax error: invalid arithmetic operator (error token is ".10")
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,电子邮件仍在发送。

更新 2

这有效。但我不确定为什么。:/

cpu_load=$(uptime | cut -d' ' -f 13 | sed '$ s/.$//')
limit=1

send_email(){
echo | mail -s "makroczsk, cpuload $cpu_load is higher than limit $limit!" $email_to
}

echo "cpuload = $cpu_load (${cpu_load%%.*}), limit = $limit"

#[[ (( ${cpu_load%%.*} > $limit )) ]] && send_email
[[ ${cpu_load%%.*} -gt $limit ]] && send_email
Run Code Online (Sandbox Code Playgroud)

ste*_*ver 11

由于多种原因,您在这里的方法注定失败。

首先,即使您获得了正确的算术比较语法,即:

[ $cpuload -gt $limit ]
Run Code Online (Sandbox Code Playgroud)

(POSIX shell 兼容)或

[[ $cpuload -gt $limit ]]
Run Code Online (Sandbox Code Playgroud)

(bash / ksh 扩展测试) 或

(( cpuload > limit ))
Run Code Online (Sandbox Code Playgroud)

bash shell 仅支持整数算术,因此您需要先修剪掉任何尾随小数,注意您的语言环境的数字表示,如 HuHa 所述

请注意,当您在 bash 中使用它时,[[ $cpuload > $limit ]]一个语法上有效的比较,但是它会“奇怪地”工作,因为它会按字典顺序逐个字符地比较 RHS 和 LHS。特别是,

$ [[ 3.0 > 10.0 ]] && echo greater || echo not greater
greater
Run Code Online (Sandbox Code Playgroud)

因为 character3在字典上大于 character 1;然而

$ [[ 03.0 > 10.0 ]] && echo greater || echo not greater
not greater
Run Code Online (Sandbox Code Playgroud)

因为 character0在字典上小于 character 1。最重要的是,如果您想在 bash 脚本中进行浮点运算,您将需要一个外部程序,例如bcorawkperl1


其次,uptime输出是为了人类可读性,而不是机器解析。特别是,时间格式因实际正常运行时间而异,例如:

(重启前)

$ uptime
 10:38:50 up 26 days, 12:33,  4 users,  load average: 0.09, 0.04, 0.00
Run Code Online (Sandbox Code Playgroud)

(重启后)

$ uptime
 10:44:37 up 3 min,  1 user,  load average: 0.17, 0.33, 0.16
Run Code Online (Sandbox Code Playgroud)

尝试对其进行标记cut -d' '特别脆弱,因为它依赖于每个字段的确切左填充量:例如,如果天数/小时数/分钟数/用户数从一位数滚动到两位数,它将失败。

相反,我建议直接从读取平均负载/proc/loadavg-uptime无论如何,这是从哪里获取它的,您可以通过以下方式确认strace

$ strace -etrace=openat uptime 2>&1 | tail -n 3
openat(AT_FDCWD, "/proc/loadavg", O_RDONLY) = 4
 12:49:38 up  2:08,  1 user,  load average: 0.00, 0.01, 0.00
+++ exited with 0 +++
Run Code Online (Sandbox Code Playgroud)

格式是简单的空格分隔字段,您可以轻松解析和测试,awk例如:

$ cat /proc/loadavg
0.52 0.58 0.59 1/5 3759

$ limit=10; awk -v limit="$limit" '$1+0 > limit {exit 1}' /proc/loadavg && echo "ok" || echo "overload"
   ok

$ limit=0.5; awk -v limit="$limit" '$1+0 > limit {exit 1}' /proc/loadavg && echo "ok" || echo "overload"
   overload
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 当然你开关能以一个壳确实支持非整数运算,如kshzsh