Bash for 具有多个条件的循环
Posted
技术标签:
【中文标题】Bash for 具有多个条件的循环【英文标题】:Bash for cycle with multiple conditions 【发布时间】:2020-08-21 17:39:15 【问题描述】:我几乎是 bash 脚本的新手,仍在学习过程中,但我试图完成相对简单的任务,但超出了我的理解范围。
我的输出文件带有标识符、机器名称和 mysql 转储的配置时间,如下所示:
id;server.name;time_in_hour
文件的每一行。
我需要的是循环,它将“time_in_hour”与备份机器上“server.name”文件夹中文件的时间戳进行比较。备份文件的路径如下:
/dumps/server.name/2020-05-06___10-49-00___sys.sql.gz
如果没有最大的备份文件。时间长度 2x “time_in_hour”(例如:实际时间 -4 小时,对于文件夹中的每个转储文件,备份计划为 2 小时),或者如果根本没有备份,脚本将打印错误输出。在理想情况下,脚本的第二个条件是检查每个转储文件的结尾是否一致,例如 grep 字符串“转储完成”。
转储文件示例结束:
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS /; /!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION /; /!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- 转储于 2020-03-02 23:58:29 完成
我仍然不能完全确定哪种工具更适合完成“约会”或“查找”任务?或者如何实际构建这种类型的嵌套循环?有多种情况...你能给我举个例子吗?
【问题讨论】:
在您的问题中添加几行 mysql 转储(无评论)。 【参考方案1】:我仍然不完全确定哪种工具更适合完成
date
或find
的任务?
这在某种程度上取决于您的要求和您尝试实现的目标。也就是说,只需创建一个没有实际备份的服务器列表,您可以使用类似
find dumps/* -mmin +120 -type f | cut - "/" -f 2 > noBackup.lst
由于我在我的一个环境中有某种类似的需求,我想展示一些可能的解决方案。
toBackup.lst
1;test1.example.com;2
2;test2.example.com;2
3;test3.example.com;2
由于我还没有完全理解 time_in_hour
的确切含义,我将保留您描述中给出的值
如果没有最大备份文件。时间长度 2x
time_in_hour
(例如:实际时间 -4 小时,文件夹中每个转储文件的备份计划为 2 小时)...
因为我认为应该每 2 小时进行一次备份。
testBackup.sh
#!/bin/bash
BOLD='\033[0;1m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
while read LINE; # from a list
do
ID=$(echo "$LINE" | cut -d ";" -f 1)
SERVERNAME=$(echo "$LINE" | cut -d ";" -f 2)
TIMESLOT=$(echo "$LINE" | cut -d ";" -f 3) # in hr
TIMESLOT=$(($TIMESLOT*60*60)) # in sec
echo -e "$BOLDID $ID$NC"
echo "Going to check backup of $SERVERNAME"
# Suppress error message if there is no directory or file
FILENAME=$(ls 2> /dev/null dumps/$SERVERNAME)
if [[ -z "$FILENAME" ]]; then
echo -e "$REDNo file found$NC"
# Since there is no backup file leave the loop and continue with next line from list
continue
else
echo "Backup file is $FILENAME"
fi
# Get backup timestamp from filename instead of modification time of the file itself
# To do so, cut out the timestamp and re-format it for further processing with date
TIMESTAMP=$(echo "$FILENAME" | cut -d "_" -f 1-4 | sed 's/___/ /g' | sed 's/-/:/3g')
echo "Backup time is $TIMESTAMP"
# To be able to calculate the difference, convert timestamp and time to seconds
MTIME=$(date -d "$TIMESTAMP" +"%s") # modification time
NOW=$(date +"%s")
DIFFERENCE=$(($NOW-$MTIME))
# Check if difference not more than the given $TIMESLOT value
echo "Allowed is an backup file age of $TIMESLOT sec"
if [ $DIFFERENCE -gt $TIMESLOT ]; then
echo -e "Backup file age of $DIFFERENCE sec is $REDtoo old$NC"
# Since the backup filename indicates it is too old, leave the loop and continue with next line from list
continue
else
echo -e "Backup file age of $DIFFERENCE sec is $GREENOK$NC"
fi
# Check if the backup file contains a valid backup
# To do so, decompress the file and gather the timestamp from last line
DUMPTIME=$(gzip --decompress --to-stdout dumps/$SERVERNAME/$FILENAME | tail -1 | cut -d " " -f 6-)
echo "Timestamp of database dump is $DUMPTIME"
# Convert timestamp from within the backup file into seconds
DTIME=$(date -d "$DUMPTIME" +"%s")
DIFFERENCE=$(($NOW-$DTIME))
# Here it is assumed that the decompression worked well and the file contained an timestamp
if [ $DIFFERENCE -gt $TIMESLOT ]; then
echo -e "Backup content age of $DIFFERENCE sec is $REDtoo old$NC"
# Since the timestamp within the backup indicates it is too old, leave the loop and continue with next line from list
continue
else
echo -e "Backup content age of $DIFFERENCE sec is $GREENOK$NC"
fi
done < toBackup.lst
这将遍历给定的主机列表,检查是否有备份文件,以及检查文件是否有效且不是太旧。您可以根据需要更改或扩展它。
感谢
How to suppress error message of a command? How to extract numbers from a string? Replace nth occurence of string in each line of a text file How can I test if a variable is empty or contains only spaces? How to break out of a loop in Bash?【讨论】:
非常感谢!这正是我想要实现的目标。以上是关于Bash for 具有多个条件的循环的主要内容,如果未能解决你的问题,请参考以下文章
[Linux Shell学习系列七]Bash循环——1for循环