因此我编写了一个简短的脚本,计划每天通过 cron 作业运行该脚本,以打包我的站点文件并将其发送到远程位置。我还计划合并数据库转储,但目前还没有做到这一点。
但是,我今天的问题是,我不确定如何记录每个命令的输出,以记录命令可能输出的错误、警告或其他相关信息。我还想安装某种故障保护装置,这样如果出现严重错误,脚本就会立即停止运行并通过电子邮件或其他方式通知我。好吧,电子邮件这件事并不那么重要,但会很好。
有人对此有什么想法吗?以下是我目前的想法。
顺便说一下,两台服务器都是运行标准 LAMP 的 CentOS 6.2。
#!/bin/sh
#################################
### Set Vars
#################################
THEDATE=`date +%m%d%y%H%M`
#################################
### Create Archives
#################################
tar -cf /root/backups/files/server_BAK_${THEDATE}.tar -C / var/www/vhosts
gzip /root/backups/files/server_BAK_${THEDATE}.tar
#################################
### Send Data to Remote Server
#################################
scp /root/backups/files/server_BAK_${THEDATE}.tar.gz user@host:/home/bak1/ftp/backups/
#################################
### Remove Data from this Server
#################################
rm -rf /root/backups/files/server_BAK_${THEDATE}.tar.gz
答案1
答案有点混乱,但请仔细阅读。
当出现任何类型的错误时让脚本立即停止运行:
set -e
这将确保如果任何您的命令失败,脚本将立即失败。其他好主意:
function error_handler() {
# This will get run when an error is detected
}
trap error_handler ERR
这将error_handler
在命令失败时运行。您还可以让EXIT
处理程序在每次脚本退出时运行代码。
要将脚本的所有输出捕获到文件中:
exec &> some_log_file
还可以在日志文件中看到脚本执行的命令(非常适合故障排除):
set -x
要使脚本抛出有关未定义变量的警告:
set -u
总而言之,使用以下命令启动脚本:
trap error_handler ERR
exec &> some_log_file
set -eux
如果您从 cron 运行脚本,则当脚本有任何输出时,它会向您发送电子邮件。如果仅在出现问题时才收到电子邮件,请cat some_log_file
在错误处理程序中输入一个,这样就完成了。
更新:回答您的其他问题。
- 为了防止错误破坏整个脚本,您可以在语句中运行该命令
if
。例如if ! <some command>; then <what do you do if it fails, or possibly nothing>; fi
- 如果有的话
trap error_handler
您还需要定义一个function error_handler
。 - 改组
set -eu
并不是set -eux
一个坏主意,但是...... ...如果您担心安全问题,则不应将 mysql 密码放在命令行上(任何运行的人
pgrep -lf mysql
都会看到它)。改用选项文件。这样您就不必担心日志文件中的密码了。option_file=`mktemp` cat > $option_file <<EOF [client] password = $DB_PASSWD user = $DB_USER EOF
然后
mysqldump
使用运行。当你不再需要它时,--default-extra-path=$option_file
不要忘记删除它。$option_file
- 使用
rsync
而不是scp
。 它对于复制相对较大的文件效果更好。
答案2
您可以将每个命令的错误重定向到特定的文件。
grep da * 2> grep-errors.txt
这会将错误从 grep 重定向到文件 grep-errors.txt。
grep da * 1>&2
这将导致程序的 stderr 输出被写入与 stdout 相同的文件描述符。
rm -rf * 2>&1
这将导致程序的 stderr 输出被写入与 stdout 相同的文件描述符
rm -f $(find / -name core) &> /dev/null
这会将程序的每个输出放置到一个文件中。如果您希望命令绝对安静地传递,这有时适用于 cron 条目。当然,您可以用某个文件替换 /dev/null 并将所有输出写入其中。
这是用于记录错误。我知道这是简单的备份脚本,但你又在重复做无用功。我认为你应该看看 Bacula。对于仅备份一台服务器来说,这是一个相当大的解决方案,但它可以满足你所有要求。备份、通知等等。你将拥有最好的备份解决方案之一。为一台或几台服务器设置它非常简单,你可以在几个小时内完成。
如果您仍想使用脚本,则应将所有错误重定向到 stdout。将此脚本添加到 cron 后,它会通过电子邮件向您发送该脚本的每个输出。您应该只检查 /etc/aliases 中的 root 条目,并在那里写邮件,如下所示:
root: [email protected]
答案3
我对剧本做了一些更新。这是新剧本。不过仍在努力,
编辑:因此,我对脚本进行了更多调整,以纳入数据库的迭代备份。以下是最新版本。我现在正在测试它。
我的新问题是:我不想在日志文件上显示数据库的密码,因此我将第一个“set”设置为“set -eu”。但我决定要查看日志文件上的脚本中正在运行哪些命令,因此在数据库迭代和转储完成后,我将“set”重置为“set -eux”。我这样做是好的做法吗?此外,如何在日志文件上显示时间戳?
#/bin/sh
#################################
### Set Vars
#################################
LOCALBAKTMP='/root/backups/files' ###~~~PLACE WHERE TMP FILES GO
LOCALBAKLOC='var/www/vhosts' ###~~~DIRECTORY TO BACKUP (NO SLASH IN FRONT)
REMOTEUSR='user' ###~~~USER AT REMOTE SERVER
REMOTEHOST='host' ###~~~REMOTE HOST ADDRESS
REMOTEDEST='/home/bak1/ftp/backups/' ###~~~FILE DESTINATION AT REMOTE
LOGDIR='/root/backups/logs/' ###~~~LOCAL BACKUP LOG DIRECTORY
DELLOGSDAYS='30' ###~~~DAYS TO STORE LOG FILES
THEDATE=`date +%m%d%y%H%M` ###~~~DATE VARIABLE
DB_BACKUP="/root/backups/files/dbs" ###~~~DB BACKUP LOCATION
LOCALDBLOC="root/backups/files/dbs" ###~~~DB FILES TO BAK
DB_USER="dbuser" ###~~~DB ROOT USER
DB_PASSWD="dbpassword" ###~~~DB ROOT PASS
HN=`hostname | awk -F. '{print $1}'` ###~~~DO NOT CHANGE
#################################
### Set Logging
#################################
trap error_handler ERR
exec &> ${LOGDIR}bak_${THEDATE}.log
set -eu
#################################
### Dump MySQL
#################################
for db in $(mysql --user=$DB_USER --password=$DB_PASSWD -e 'show databases' -s --skip-column-names|grep -vi information_schema);
do mysqldump --user=$DB_USER --password=$DB_PASSWD --opt $db | gzip > "$DB_BACKUP/mysqldump-$HN-$db-$(date +%Y-%m-%d).sql.gz";
done
#Log commands for the rest of the script
set -eux
#################################
### Create Archives
#################################
tar -cf ${LOCALBAKTMP}/server_BAK_${THEDATE}.tar -C / ${LOCALBAKLOC}
gzip ${LOCALBAKTMP}/server_BAK_${THEDATE}.tar
tar -cf ${LOCALBAKTMP}/db_BAK_${THEDATE}.tar -C / ${LOCALDBLOC}
gzip ${LOCALBAKTMP}/db_BAK_${THEDATE}.tar
tar -cfz full_BAK_${THEDATE}.tar.gz *_BAK_${THEDATE}.tar.gz
#################################
### Send Data to Remote Server
#################################
scp ${LOCALBAKTMP}/full_BAK_${THEDATE}.tar.gz ${REMOTEUSR}@${REMOTEHOST}:${REMOTEDEST}
#################################
### Remove Data from this Server
#################################
rm -f ${LOCALBAKTMP}/*_BAK_${THEDATE}.tar.gz
rm -rf ${DB_BACKUP}/*.sql.gz
find ${LOGDIR}* -mtime +${DELLOGSDAYS} -exec rm {} \;