Linux 如何在出现错误时不中断循环的执行并将其写入变量?
我想通过scp备份mikrotiks。此脚本从hosts.txt循环通过主机。逐个连接到列表中的每个设备。执行备份和所有操作。如果在某个阶段无法连接到设备,则会形成一个空备份,然后发送到云。 我想查查。如果无法连接到主机,则逐行将此主机写入变量,然后转到下一个设备。接下来,我将通知所有失败的连接。 问题是,只有第一个错误被写入变量,所有后续错误都被忽略。 告诉我谁知道什么Linux 如何在出现错误时不中断循环的执行并将其写入变量?,linux,bash,awk,sed,Linux,Bash,Awk,Sed,我想通过scp备份mikrotiks。此脚本从hosts.txt循环通过主机。逐个连接到列表中的每个设备。执行备份和所有操作。如果在某个阶段无法连接到设备,则会形成一个空备份,然后发送到云。 我想查查。如果无法连接到主机,则逐行将此主机写入变量,然后转到下一个设备。接下来,我将通知所有失败的连接。 问题是,只有第一个错误被写入变量,所有后续错误都被忽略。 告诉我谁知道什么 #!/bin/bash readarray -t hosts < hosts.txt DATE=$(date +'%
#!/bin/bash
readarray -t hosts < hosts.txt
DATE=$(date +'%Y-%m-%d_%H-%M-%S')
ROS='<br>'
ERR=( )
#Get values from main list
for host in ${hosts[*]}
do
#Get values from sub list
hostname=($(echo ${host} | tr "_" " "))
echo ${hostname[0]} - ${hostname[1]}
#connect & backup & transfer & archive & rm old files & moove to cloud
if ssh backup@${hostname[0]} -C "/system backup save name=${hostname[1]}_$DATE"; then
scp backup@${hostname[0]}:"${hostname[1]}_$DATE.backup" ./
ssh backup@${hostname[0]} -C "rm ${hostname[1]}_$DATE.backup"
tar -czvf ./${hostname[1]}_$DATE.tar.gz ${hostname[1]}_$DATE.backup
scp ./${hostname[1]}_$DATE.tar.gz my@cloud.com:/var/www/my.cloud.com/backups/mikrotik/
rm ${hostname[1]}_$DATE.backup ${hostname[1]}_$DATE.tar.gz
ROS=$ROS${hostname[1]}"<br>"
else
ERR+=(${hosts[*]} "is not ready")
fi
done
正如我在评论中指出的,您误用了数组表示法。您的行
ERR=(${hosts[*]}”未就绪”)
应该是ERR+=(${hosts[*]}”未就绪”)
并且您应该将ERR
定义为数组,而不是标量:ERR=()
例如,或者声明-a ERR
。类似于ROS
下面是一个测试脚本,它避免了所有的ssh
和scp
工作,以演示通过和失败主机的列表是否工作—阵列主机
、ROS
和错误
是否正确处理
请注意,“${ERR[@]}”
使用双引号和@
代替无引号和*
。差异很重要,因为数组中的值包含空格。尝试其他选择。还要注意的是,printf
始终打印,即使格式字符串中没有与%s
对应的参数。因此,在调用printf
之前,需要检查数组中的元素数
#/bin/bash
#需要Bash4.x-Mac上的Bash3.2不支持readarray
#readarray-t hosts
输出:
==PASS===[passed-1 passed]
==通过==[通过-3通过]
==通过==[通过-5次通过]
!! 失败!![失败-2失败]
!! 失败!![失败-4失败]
==通过==[通过-1通过]
==通过==[通过-3通过]
==通过==[通过-5次通过]
!! 失败!![失败-2失败]
!! 失败!![失败-4失败]
很抱歉,备份您的数据失败太多 记录的是第一台或最后一台不可用的主机?您的行
ERR=(${hosts[*]}”未就绪”)
应该是ERR+=(${hosts[*]}”未就绪”)
并且您应该将ERR
定义为数组,而不是标量:ERR=()
例如,或者声明-a ERR
。类似于ROS
。将脚本复制/粘贴到中,并修复它告诉您的问题,如果您仍然有问题,则将结果发布到问题中。@JonathanLeffler感谢您的替换,现在我将修复它并重试。@JonathanLeffler第一个不可用的主机已写入文件。由于您显示的代码中没有任何状态信息写入文件,因此我断定您讨论的是尚未显示的代码。您可能应该将ROS=$ROS${hostname[1]}“
”
写成ROS=“$ROS${hostname[1]}
”
,将整个RHS括在双引号中。我相信您知道这一点,但为了操作起见-不要对未导出的变量名(ROS
和ERR
)使用所有大写字母,看到了,我故意忽略了这一点,因为这与我学习编写shell脚本的方式相反,但您可能最适合这些天学习shell脚本的人。事实上,我对环境变量大多使用大写下划线的名称,而对其他变量使用小写下划线的名称。还有一个关于太的问题(链接自Unix和Linux问题)。在没有外部胁迫的情况下,我很少(如果有的话)使用小写的环境变量名。这听起来与我给出的建议并不矛盾,对我来说也是一样的——对环境变量使用大写,否则使用小写。也许我用了双底片,这就不清楚了!
hosts.txt
10.10.8.11_CAP-1
10.10.9.12_CAP-2
10.10.10.13_CAP-3