我是Bash脚本的新手。我编写了一个脚本来帮助我从一堆服务器中使用ssh获取一些信息。第一组设备的IP地址从101到148,另一组从201到210。
#!/bin/bash
BASE=192.168.11
SD_START=101
SD_END=148
HD_START=201
HD_END=210
SD_counter=$SD_START
HD_counter=$HD_START
while [[ $SD_counter -le $SD_END ]]
do
ip=$BASE.$SD_counter
ssh $ip command1
SD_counter=$(($SD_counter +1))
if [ "$SD_counter"==148 ]
then
while [[ $HD_counter -le $HD_END ]]
do
ip=$BASE.$HD_counter
ssh $ip command2
HD_counter=$(($HD_counter +1))
done
fi
done > log_SD_HD
echo "Done!"
但由于某种原因,command1首先在192.168.11.101上执行,然后在ip范围192.168.11.201-192.168.11.210执行command2,这是第二个while循环。 之后,第一个while循环一直持续到结束。 为什么会这样?我希望第一个while循环在第二个while循环之前完成。有人可以指出我做错了吗?
答案 0 :(得分:2)
没有理由将循环嵌套在您展示的内容中:
#!/bin/bash
BASE=192.168.11
SD_START=101
SD_END=148
HD_START=201
HD_END=210
SD_counter=$SD_START
HD_counter=$HD_START
while [[ $SD_counter -le $SD_END ]]
do
ip=$BASE.$SD_counter
ssh $ip command1
SD_counter=$(($SD_counter +1))
done> log_SD_HD
while [[ $HD_counter -le $HD_END ]]
do
ip=$BASE.$HD_counter
ssh $ip command2
HD_counter=$(($HD_counter +1))
done>> log_SD_HD
echo "Done!"
答案 1 :(得分:2)
<强>更新强>
提示:您始终可以使用#!/bin/bash -x
来跟踪和调试脚本。
正如V_Maenolis所展示的那样,使用两个while
循环是一个好主意。但是,要回答关于脚本出现问题的问题,请尝试使用
替换
if [ "$SD_counter"==148 ]
带
if [ "$SD_counter" -gt 148 ]
对我有用。
所以有两个错误
==
运算符之前和之后应该有一个空格,也就是说,使用A == B
NOT A==B
SD_counter == 148
的逻辑不正确。因为当SD_counter达到148时,你的脚本将进入第二个while循环,你将获得147, 201, ..., 210, 148
。使用-gt
可以避免此问题。答案 2 :(得分:2)
@ 0x1cf的回答提供了正确的指针:
[ "$SD_counter"==148 ]
没有按预期工作。
具体来说:"$SD_counter"==148
基于bash的字符串合成规则,扩展为单字符串文字:$SD_counter
的值与文字{{{1}连接{1}},生成的字符串文字被视为布尔值。
由于布尔上下文中的非空字符串始终求值为==148
,因此true
[ "$SD_counter"==148 ]
始终求值为true
>
除此之外:在bash中你应该使用==
而不是[[ ... ]]
- 它更强大并提供更多功能。
另请注意(正如@ 0x1cf所说) - 如果使用[ ... ]
或[ ... ]
- 使用算术运算符是正确的选择处理数字时:[[ ... ]]
,-eq
,-ne
,-lt
,-le
或-gt
。< / p>
但一般来说,使用-ge
表达式 - 算术评估 - 提供更多的数字灵活性 - 请参阅下文。
即使使用算术评估 - (( ... ))
,您的代码可以大大简化(请参阅(( ... ))
中的ARITHMETIC EVALUATION
部分):
它允许您使用 C风格的算术和布尔表达式。 如果我们将此与bash的 数组变量结合使用,您的代码可以简化为:
man bash
注意:
#!/usr/bin/env bash
BASE=192.168.11
START_INDICES=( 101 201 )
END_INDICES=( 148 210 )
COMMANDS=( command1 command2 )
numRanges=${#START_INDICES[@]}
for (( range = 0; range < numRanges; ++range )); do
cmd=${COMMANDS[range]}
for (( i=${START_INDICES[range]}; i<=${END_INDICES[range]}; ++i )); do
ip=$BASE.$i
ssh $ip $cmd
done
done > log_SD_HD
表达式DIFFER来自正常的bash分配和条件:
(( ... ))
$
)=
可以工作。 (( SD_counter==148 ))
创建一个包含元素( string1 ... )
,string1
的数组; ...
返回数组变量${#arrayVar[@]}
的元素数; arrayVar
返回带有(${arrayVar[ndx]}
- )索引0
的元素。
ndx
之类的ALL-UPPERCASE变量名称,因为它们可能与环境变量冲突,而环境变量通常都是大写的。