- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我的 bash 脚本遇到了一些奇怪的行为。它基本上是一个脚本,如果第一次失败,它会尝试多次 ping 远程主机。我这样做是为了排除任何误报。我想我会通过编写一个调用自身并再次尝试 ping 的递归函数来快速实现这一点。
我的问题是返回值。我发现该函数多次返回返回值,对应于递归的次数。这很奇怪。例如在我下面的代码中,ip_up() 函数应该返回 1 表示远程主机启动,0 表示关闭。但是,当远程主机关闭时,该函数会返回两次 0,这与所做的递归相对应。
我的代码可能有什么问题,或者 bash 是这样工作的吗?
#!/bin/bash
ip_up(){
server_ip=$1
trials=$2
max_trials=2
status=0
echo "server ip is: $server_ip, trial $trials" >&2
if ping -i 1 -c 3 "$server_ip" &> /dev/null
then
status=1
else
status=0
while (( "$trials" < "$max_trials" )); do
echo -e "$server_ip is down: Trial $trials, checking again after 1 sec" >&2
sleep 1
((trials++))
ip_up "$server_ip" "$trials"
done
fi
echo "$status"
}
status=$(ip_up "$ip" 1)
echo -e "the returned status is: ====$status====\n"
if [ "$server_status" -eq 0 ]; then
msg="$timestamp: Server $hostname ($ip) is DOWN"; echo "$msg"
fi
<<'COMMENT'
//results
$ ./check_servers.sh
checking box1(173.36.232.6)
server ip is: 173.36.232.6, trial 1
173.36.232.6 is down: Trial 1, checking again after 1 sec
server ip is: 173.36.232.6, trial 2
the returned status is: ====0
0====
./check_servers.sh: line 41: [: 0
0: integer expression expected
Sat Jun 4 15:16:11 EAT 2016 box2 (173.36.232.7) is UP
checking box2 (173.36.232.7)
server ip is: 173.36.232.7, trial 1
the returned status is: ====1====
COMMENT
最佳答案
我无法想象在很多情况下,我会在循环中经常使用具有一秒延迟的代码,以至于值得将其作为函数编写 — 我会使用相对直接(迭代)的脚本。但是,如果您确定这对您有好处,那么将脚本转换为函数绝非不可能。你的情况和我的不一样。
#!/bin/sh
[ $# = 1 ] || [ $# = 2 ] || { echo "Usage: $0 ip-address [max-trials]" >&2; exit 1; }
server_ip="$1"
maxtrials="${2:-2}"
trial=1
while echo "server: $server_ip, trial $trial" >&2
! ping -i 1 -c 3 "$server_ip" > /dev/null 2>&1 || exit 0
do
trial=$(($trial + 1))
[ "$trial" -gt "$maxtrials" ] && break
echo "$0: $server_ip is down: checking again after 1 sec" >&2
sleep 1
done
echo "$(date +'%Y-%m-%d %H:%M:%S'): Server $server_ip is DOWN"
exit 1
第一段代码设置控件,默认为 2 次尝试。
while
循环控制包含echo
,然后尝试ping
IP 地址(或主机名)。如果命令成功(主机可 ping 通),则 ! ping
状态为 false,因此 || exit 0
被执行,脚本以 0 状态退出,表示成功(主机可 ping 通)。如果命令失败(主机不可 ping),则 ! ping
状态为真,所以 || exit 0
不执行,进入循环体。如果达到限制,它会增加试验编号并中断循环。否则,它会打印其消息并休眠并返回到循环的开始。
仅当未执行 exit 0
时才会到达结束 block ,因此 ping
失败且服务器“关闭”(或不存在)。然后您会收到一 strip 时间戳的消息,指示服务器已关闭,并以非零状态退出以指示失败。
可能还有无数种其他方法可以做到这一点。我可能会更符合错误消息——例如,我可能会保存 arg0="$(basename "$0".sh)"
然后使用 $arg0
作为所有消息的前缀(或者可能在时间戳之后添加)。可以对此进行调整以报告服务器已启动。该代码适用于 POSIX shell,而不仅仅是 Bash(因此 dash
接受它,例如,Korn shell 也是如此,但 Heirloom (Bourne) Shell 不接受,因为它既不喜欢 $(…)
或 $((…))
).
也可以将它写成一个简单的计数循环,测试 ping
的状态,成功退出,然后进行报告和重试。然而,当循环将退出而不双重测试 $trial
的值时,要避免最后一个 sleep 1
是很棘手的。这在运行时并不昂贵,但它是重复的来源,而 DRY(不要重复自己)是一个值得遵守的原则。
#!/bin/bash
[ $# = 1 ] || [ $# = 2 ] || { echo "Usage: $0 ip-address [max-trials]" >&2; exit 1; }
server_ip="$1"
maxtrials="${2:-2}"
for ((trial = 1; trial <= maxtrials; trial++))
do
echo "server: $server_ip, trial $trial" >&2
if ping -i 1 -c 3 "$server_ip" > /dev/null 2>&1
then exit 0
elif [ "$trial" -lt "$maxtrials" ]
then
echo "$0: $server_ip is down: checking again after 1 sec" >&2
sleep 1
fi
done
echo "$(date +'%Y-%m-%d %H:%M:%S'): Server $server_ip is DOWN"
exit 1
我并不完全热衷于此,但它适用于 Bash 和 Korn shell。
将最后一个脚本转换为函数基本上是微不足道的——将 exit
语句更改为 return
语句,并在其周围包裹一个函数开始和结束:
#!/bin/bash
function upip()
{
[ $# = 1 ] || [ $# = 2 ] || { echo "Usage: $0 ip-address [max-trials]" >&2; return 1; }
server_ip="$1"
maxtrials="${2:-2}"
for ((trial = 1; trial <= maxtrials; trial++))
do
echo "server: $server_ip, trial $trial" >&2
if ping -i 1 -c 3 "$server_ip" > /dev/null 2>&1
then return 0
elif [ "$trial" -lt "$maxtrials" ]
then
echo "$0: $server_ip is down: checking again after 1 sec" >&2
sleep 1
fi
done
echo "$(date +'%Y-%m-%d %H:%M:%S'): Server $server_ip is DOWN"
return 1
}
保存在upip-func.sh
中,我读取函数:
$ . upip-func.sh
$ upip www.google.com
server: www.google.com, trial 1
$ echo $?
0
$ upip ping.google.com
server: ping.google.com, trial 1
bash: ping.google.com is down: checking again after 1 sec
server: ping.google.com, trial 2
2016-06-06 00:35:18: Server ping.google.com is DOWN
$ echo $?
1
$ if upip www.google.com; then echo OK; else echo Fail; fi
server: www.google.com, trial 1
OK
$ if upip ping.google.com; then echo OK; else echo Fail; fi
server: ping.google.com, trial 1
bash: ping.google.com is down: checking again after 1 sec
server: ping.google.com, trial 2
2016-06-06 00:38:32: Server ping.google.com is DOWN
Fail
$
关于linux - Linux bash 递归函数的返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37630609/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!