一个近乎完美的rsync over ssh备份脚本

2022-02-25 22:22:18

对于任何存储数据的人来说,创建备份都是一项基本需要。在专用服务器、Linux操作系统和rsync软件的帮助下,您可以通过SSH连接安全高效地从任何计算机检索数据,并将其存储在备份中。另一边是另一台Linux服务器、Mac电脑还是Windows电脑都无关紧要。但是一旦你有了超过几个文本文件,你就必须精确地控制这个过程。该脚本包含一些重要元素,在处理大量数据和慢速互联网线路时,这些元素是必不可少的。

它区分了TOSSH和ssh,即服务器是否获取某些内容,或者是否将某些内容推送到备份服务器(TOSSH)。如果是FROMSSH,则计算机上没有要备份的访问数据。到备份的连接凭据始终是加密特洛伊木马的第一个目标,因此备份服务器最好自己获取数据,即它是连接到要备份的计算机的凭据->;fromsh

它区分了用每个月的天数覆盖文件夹,或创建以完整日期为名称的新文件夹->;蒙特罗塔特

它可以检查要备份的卷是否通过USB连接到计算机->;MOUNTPOINT(我不使用这个。)

它可以通过备份过程的日志启动邮件发送。

它可以删除源和备份中不再存在的文件。

使用存储的密钥(使用SSH密钥,而不是密码!)备份服务器通过SSH(从SSH)拨号要备份的计算机。在那里,它将要备份的卷上的文件与符号链接指向的文件夹中的文件进行比较,该文件夹名为“last”。然后根据当天的编号(例如“02”)创建一个新文件夹,所有新的或更改的文件都存储在其中。在已经存在的文件上,在新文件夹中创建一个硬链接,以便这些文件都“存在”在新文件夹中。删除的文件不会获得硬链接。如果一切就绪,则符号“last”现在指向新文件夹。在接下来的一个月里,只需使用当前文件夹(MONTHROTATE)覆盖具有相同日数的旧文件夹。日期和每个传输的文件都会写入日志,日志会作为额外文件创建,每次都会被覆盖。最后,这些信息将作为邮件发送。备份脚本每天通过特殊备份用户(没有sudo权限)的crontab启动。

如果rsync进程耗时超过24小时,那么这些进程会重叠和累积(新进程启动时,旧进程还没有准备好),相互阻塞,什么都不起作用->;因此,新流程只有在前一个流程完成后才能启动。

在包含许多文件的大容量中,日志文件变得太长,无法再放入电子邮件中,因此电子邮件将不再发送->;对于大容量,只应记录错误。

如果发生错误,则仍会创建指向新创建文件夹的符号链接,当前标记为name。这导致下一次备份时,完整备份会再次传输。对于数TB的数据,通过互联网传输数据可能需要一个月的时间->;只有在之前没有错误时才更改符号链接,否则将符号链接保留到正常文件夹,直到再次进行无错误备份。缺点:即使手动启动脚本,也不可能在同一天进行第二次备份。

备份服务器只需要很短的时间,但可以运行一整天->;同时使用单独的脚本关闭服务器,但前提是当前没有运行备份,或者当前有人通过SSH登录。将此任务与备份用户分开,并通过管理用户或central/etc/crontab执行,因为这需要根权限。(这不是本博客的一部分。)

为了保持跟踪,一个文件存储所有日志条目,一个接一个,每个条目只有几行->;所有日志

#!/bin/bash#避免与其他rsync进程发生冲突#传递给脚本的分钟数#21h*60min=1260分钟分钟分钟=1260#确保没有其他人在使用rsync#on=$(ps aux | grep-c rsync)#如果有人在使用rsync#grep也在生成一个条目so-gt 1而[$pro u on-gt 1]do sleep 60分钟=$($minutes-1))#如果[$minutes-lt 60],则第二天无需开始;然后退出0 fi pro_on=$(ps aux | grep-c rsync)完成

这是检查其他rsync进程是否正在运行的块。它改编自以下代码“让您的服务器打盹”:

在第一行中,你说“bash”应该被委托执行。

“分钟=1260”意味着该脚本启动的延迟时间最多应为21小时。此后,脚本将不会执行,因为cron进程将在下一轮备份中启动。

“pro_on=$(ps aux | grep-c rsync)”,正在运行的进程,这里是“rsync”,grep命令本身也会在服务器上生成一个进程,这就是为什么您必须使用“大于1”即“大于1”的原因。

之后,它进入一个while循环,每轮以“sleep 60”休眠一分钟,然后检查是否仍有多个grep rsync进程在运行。然后,分钟总是按1倒计时,如果在21小时结束之前,时间不足60分钟,则不再值得运行脚本,“退出0”中止。之后,cron将在第二天的常规时间重试。当另一个rsync进程需要超过20小时时,就会发生这种情况。

#使用rsync#本地模式、tossh模式、fromsh modeSOURCES=(/Volumes/my#u volume/)TARGET="进行简单备份/srv/备份卷";#用"编辑或评论#"MONTHROTATE=MONTHROTATE#使用DD而不是yymmdrsyncconf=(-delete--exclude=/Volumes/Raid/.DocumentRevisions-V100--exclude=/Volumes/Raid/.temporary items--exclude=/Volumes/Raid/.apdisc)MAILREC=";我的家[email protected]"SSHUSER=";linux#U备份用户";fromsh=";[email protected]"#托什=";tossh服务器";SSHPORT=22222支架=34/垃圾箱/山";;FGREP="/bin/fgrep";;SSH="/usr/bin/ssh";LN="/垃圾箱/垃圾箱";;ECHO="/bin/echo";;日期="/银行标识代码/日期";;RM="/垃圾箱/rm";DPKG=#34/usr/bin/dpkg";;AWK="/usr/bin/awk";;邮件="/usr/bin/mail";切割=和#34/usr/bin/cut";;TR="/usr/bin/tr";;RSYNC="/usr/bin/rsync";LAST=";最后";;INC="--link dest=$TARGET/$LAST";;LS="/垃圾箱/垃圾箱和#34;

源是一个数组,可以包含多个源,由一个空格分隔。SOURCES在末尾有一个斜杠,这样就不会每次生成文件夹/user/Volumes/Data_文件夹。

源如果源文件末尾有一个“/”,则只复制内容,而不复制最后指定的文件夹。

SOURCES是一个数组,稍后将使用${SOURCES[@]}访问它。可以用空格分隔多个源。然后,日志中会有单独的输出,因为每个源都会处理一个“do循环”。

目标的末尾没有斜杠,如果缺少斜杠,将在以后自动添加斜杠。

“删除”表示在源文件中删除的文件也在目标文件中删除。一些点文件(.file)有时,从源头上提出阅读问题,以便最好将其排除在外。问题是,它们在读取要复制的文件和复制过程之间发生变化。这会导致一个错误。由于RSYNCCONF是一个数组,如果需要,可以在这里放置更多rsyn标志。

由于在一个月内,总是将日期指定为文件夹,因此在下个月的第4天,带有日期编号(例如“04”)的相应文件夹将再次被覆盖。如果不适用,则可以对带有完整日期的文件夹使用较长的日期。您每天都会收到一个新文件夹,然后应不时删除旧文件夹。

删除似乎不会删除仍然需要的文件,因为它们是硬链接。这些链接可以是指向一个文件的多个链接,只要硬链接仍然存在(来自另一个day文件夹),文件就不会被删除。新的备份将生成另一个指向该文件的新硬链接。这就是为什么如果你跳过一天似乎不成问题的原因。(至少我是这样理解的,但在Linux“ls-la”输出中,没有看到超过一个硬链接)。

为了跟踪序列,我在脚本中添加了一个“所有日志”文件,见下文。

在每种情况下,最后一个备份文件夹都有“最后一个”的符号链接。带有“最后一个”的链接文件夹用于比较新旧文件。只将新文件复制到备份中。

(Bash变量不必大写,这只是作者的风格)。

通过MAILREC指定日志邮件的目标地址。注意,邮件在原始脚本中包含保存文件的完整列表。这可能是几百MB,然后卡在邮件服务器中。这就是为什么我后来只在日志文件中包含错误(至少对于大型备份是这样)。见下文。

从ssh或TOSSH,我们从这里的一个源备份,因此从ssh。参数需要服务器连接。FROMSSH很重要,因为这样就无法访问正在备份的服务器上的备份数据。这对于加密特洛伊木马非常重要,因为它们会查找这些信息,然后首先对备份进行加密。

单个程序存储在变量中,这是一种有趣的方法,可以调用脚本程序,并确保即使没有在path变量中列出它们,也能找到它们。

LAST指定符号链接文件夹的名称“last”则是指向最后一次备份的sym链接。

因为我以后需要“ls”list命令,所以我也将其与完整路径一起放入变量中。但是“ls”不仅在bin中可用,在sbin中也可用,我从bin中获取它。

每次备份后都会通过电子邮件发送日志文件,然后再次覆盖。在你的电子邮件程序中,你只剩下收集的电子邮件,除了没有太多的文件,而且由于邮件的大小,邮件没有发送。这就是为什么我希望有一个“全天日志文件”,列出所有备份,有错误,但没有完整的备份文件列表。(进一步,我关闭了文件列表:默认为:INC 2>;$log,而不是2>;>;$1,然后列出正常和错误输出)。该语句是一个函数,“\n”生成一个新行,并$*“包含您为函数提供的所有参数。在这里,您将传递日志文本,然后整个过程将在结尾处写入一个新文件。”,如果它不存在也会被创建。“e”开关使echo评估反斜杠,没有反斜杠就没有断线。

此时,“0美元”包含脚本的名称,因此日志文件的命名与脚本加上“log”类似(例如:backup_script.sh.log)。之后,完整的日期/时间将写入日志文件。因此,您可以看到备份过程何时开始。在脚本完成后,最后还有一个日期/时间条目。你会看到花了多长时间。

由于其他文件夹已附加到目标文件夹,因此需要在末尾加斜杠。在这里,它被确保永远存在。

#zazu检查今天的数字是否与#符号链接#34相同;最后";到编号的文件夹#一天也没有2次备份-给出一个ERRORHEUTE=$($DATE+%d)cd$TARGETLAST_符号链接=$($LS-l | grep^l | grep-o";[0-9][0-9]$";)cd/home/sicherung/bin

首先,将月份的日数写入变量“今日”:01或02等。然后,我用“cd”将其更改为目标目录,并用“ls”和选项“l”搜索目标目录中是否有行,它的开头有一个“l”,因此它是一个符号链接。然后我将最后两个数字单位(文件夹名称)放入变量“last_symlink”中。之后,我带着“cd”返回脚本所在的目录,这样以后日志文件也会写入其中,而不是写入目标目录。

如果[$HEUTE-ne$LAST_符号链接];然后……代码部分7a到7e在这里……否则$ECHO";由于一个月没有备份或只有错误(该月的今天和最后一次备份的日期具有相同的编号),从${TODAY}开始保留最后一次备份,没有';不要给文件夹加满水。今天没有备份,下一次备份是明天" >>;$LOG ERROR=1fi

长“如果括号”:这里我说,如果符号链接指向与今天日期相同的日期,那么至少一个月内,所有事情都会出错。要么一个月内没有备份(Mac上的raid已关闭),要么所有备份都以错误结束,这就是为什么不再创建带有“last”的符号链接。

因此:只有在情况并非如此(“ne”)时,才开始新的备份,否则保留当天的完整备份,并尝试在第二天进行新的备份。

注意:只有在备份成功的情况下,才会创建一个带有“last”的新符号链接。否则,您的情况是,符号链接和rsync上出现了一个损坏的备份或不完整的备份,然后重新生成整件事,并对整个数TB的数据进行备份。

再往下是“else”,因此在标签相等的情况下,会生成一个错误,并将其写入日志,并给出解释。

如果–“z”为零装入点,因此变量文本为空,则使用“z”从今天开始的零个月旋转表示完整日期,否则仅表示当天的月数“$date+%d”。整个事件再次包含在带$sign的括号中,以便首先计算括号内容,然后将新信息传递给变量“TODAY”,这也是在这里形成的。最后,文件夹被称为“01”或“20220101”。

在这里,SSH访问部分(稍后在rsync命令中)被写入变量“S”,该变量也是通过该命令创建的。

来源于"${来源[@]}";do#fromsh–如果[";$S";]&&;[";$fromsh";]&&;[z";$TOSSH";];然后是$ECHO"$RSYNC-e\"$S\"-avR\"$fromsh:$SOURCE\"${RSYNCCONF[@]}$TARGET$TODAY$INC">>$记录#仅记录错误#34;2>>$日志";因为记录所有备份的文件会使邮件程序崩溃,所以原始的#34>>$日志#2>&;1" $RSYNC-e"$S"-avR和#34$fromsh:\"$资料来源34" "$ {RSYNCCONF[@]}""$目标"$今天$INC 2>>$如果[$?-ne 0]记录;然后错误=1 fi fi#TOSSH–I';如果[";$S";]&&;[";$TOSSH";]&&;[-z";$fromsh";];然后是$ECHO"$RSYNC-e\"$S\"-avR\"$来源\";${RSYNCCONF[@]}\"$TOSSH:$TARGET$TODAY\"$公司">>$日志$RSYNC-e"$S"-avR和#34$来源""${RSYNCCONF[@]}""$托什:34岁$目标34$今天"$公司>>$日志2>&;1如果[$?-ne 0];然后错误=1 fi#本地备份–I';如果[-z";$S";],我就不用这里了;然后是$ECHO"$RSYNC-avR\"$资料来源34${RSYNCCONF[@]}$TARGET$TODAY$INC">>$日志$RSYNC-avR"$来源""${RSYNCCONF[@]}""$目标"$今天$INC>>$日志2>&;1如果[$?-ne 0];然后错误=1 fi fidone

第一个块只是将完整的rsync命令写入日志文件,这样您就可以看到执行了什么。

然后,第二个块实际执行rsync,并将rsync报告给“标准输出”和“标准错误”的内容写入日志文件:>>$日志2>&;1“错误”2也会被发送到stdout&;1“,因此也会写入最后的日志文件。对于我来说,它只是“2>;”,因此,只记录错误,否则文件会变得太大(40TB),并记录您传输的每个文件。

如果上一次操作的退出状态不成功($?-ne 0),则“ne”不等于0=成功,则变量ERROR=1。然后,该变量在电子邮件主题中生成“ERROR”一词。

“-e”代表远程,您必须在此处指定协议SSH。(-e、-rsh=命令指定要使用的远程shell)

\“$SOURCE\”是do循环将处理的相应源。

$INC链接目的地,最后的sym link仍然在末尾指定–link dest=last

脚本中转义的内容和引号中的内容都很有趣。

引用单“x”和双“y”表示命令应连续解释。触摸“文件1触摸”文件1

对于变量,“双引号”意味着变量的内容应该在这里,而围绕变量的单“变量”引号只打印变量名=变量

如果[";$S";]&&;[";$TOSSH";]&&;[-z";$fromsh";];然后是$ECHO"$SSH-p$SSHPORT-l$SSHUSER$TOSSH$LN-nsf$TARGET$TODAY$TARGET$LAST">>$LOG$SSH-p$SSHPORT-l$SSHUSER$TOSSH"$LN-nsf\"$目标34$今天34岁$目标34$最后">>$日志2>&;1如果[$?-ne 0];然后错误=1 fifi

对于TOSSH,符号链接设置在末尾。不适用于我。

##zazu添加了[-z";$ERROR";],如果出现错误,则无符号链接([";$S";]&&;[";$fromsh";]&&;[-z";$TOSSH";]&&;[z";$ERROR";])|([-z";$S";]);然后是$ECHO"$LN——nsf$TARGET$TODAY$TARGET$LAST">>$日志$LN-nsf"$目标"$今天"$目标"$最后>>$日志2>&;1如果[$?-ne 0];那么错误=1fi

这里的符号链接是在fromsh的情况下设置的。首先将命令写入日志,然后使用$LN执行,该命令指向命令“LN”。如果命令打印了一些内容,则它将位于日志文件的末尾。如果出现错误,则错误=1用于邮件主题。

如果([";$S";]&&;[";$fromsh";]&&;[-z";$TOSSH";]&&;[z";$ERROR";])|([-z";$S";]);然后

如果发生错误,则不会写入任何符号链接,即“last”仍将指向旧的完整备份。否则,如果出现错误,服务器将从一开始就进行完整备份,这可能意味着需要一个月的传输时间,需要大量备份。

其他$ECHO";由于一个月没有备份或只有错误(该月的今天和最后一次备份的日期具有相同的编号),从${TODAY}开始保留最后一次备份,没有';不要给文件夹加满水。今天没有备份,下一次备份是明天" >>$日志错误=1 fi

注意:“else”指的是如果今天与symlink last的当天相同,则更大的if循环。

在实际过程结束时,完整的日期/时间会再次写入日志,这样您就可以看到备份花费了多长时间以及何时完成。

如果[-n";$MAILREC";];那么如果[$ERROR];然后是$MAIL-s";错误备份$LOG"$MAILREC<$LOG#zazu all LOG all#logprint#34;错误34"$(<;$LOG)和#34;else$MAIL-s";备份$LOG"$MAILREC<$LOG#zazu all LOG all#logprint#34$(<;$LOG)和#34;菲菲

如果MAILREC不为空(-n),则如果出现错误,请在主题中写入“错误备份+日志文件名$log”,否则只需“备份+日志文件名”$日志包含日志文件的名称<$LOG评估文件的内容,该文件位于$LOG中

在下面,我启动脚本开头定义的函数“all_logprint”。然后将参数“Error____\n”加上一行末尾“Error\n”传递给函数的echo命令。下划线只是为了让您更好地看到错误文本。$(<;LOG)“从日志中的文件名获取文件内容变量,然后将其写入bu脚本的“全天名称”。“sh.log”文件。

在“所有日期”中,只列出了单个备份,以及错误和有关运行时开始、运行时结束、执行的命令以及可能通过标准输出的信息。

“u”代表用户,“g”代表团体,“a”代表所有人。

要每天运行脚本,需要在crontab o中输入一个条目

......