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】:

我仍然不完全确定哪种工具更适合完成datefind 的任务?

这在某种程度上取决于您的要求和您尝试实现的目标。也就是说,只需创建一个没有实际备份的服务器列表,您可以使用类似

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基础7-9 Bash编程--for循环语句

[Linux Shell学习系列七]Bash循环——1for循环

Linux基础之bash脚本进阶篇-循环语句(for,while,until)及其特殊用法

bash脚本编程之for循环及应用

Bash脚本,while循环中的多个条件

Bash编程 循环与分支