神代綺凛の随波逐流

每日自动将你的网站备份到Github 告别数据丢失


当前页面是本站的「Baidu MIP」版。查看和发表评论请点击:完整版 »

最近听到许多数据丢失的惨况,有人提议为何不用 Github 去备份网站?而且这样还能看到每次 commit 的更改情况,随时任意回档。一拍大腿,亲自试验,做出成品,写下文章,一气呵成(

Head Pic: 「レイマリなプレイマット」/「望月椎那」[pixiv]

将网站自动备份到 Github

Github 已经允许免费用户创建无限量的私有 repo,皆大欢喜

本文将会给具体实现步骤,以及过程中用到的所有命令的解释

步骤是死的,人是活的,在一些不需要完全遵守的地方(比如各种使用的路径之类的)可以根据自己的需要和习惯自行改变

1. 一点微小的事先准备

首先的首先,你当然需要一个 Github 账户(

然后接下来是在服务器上的操作:

进入一个你喜欢的安全的目录,此处直接以/root为例

参考下命令创建一个 RSA 密匙

cd /root
ssh-keygen -t rsa

然后根据提示输入生成密匙的文件名,此处举例输入github,要你输入 passphrase 的时候直接不输入回车就行

完成后会有类似这样的显示,并且你会在当前目录下得到githubgithub.pub这两个文件

接着用cat命令查看github.pub文件的内容,并复制下来

cat github.pub

还没完,回到你的 Github 页面,点右上角头像,Settings,左边“SSH and GPG keys”,右上角“New SSH key”

然后将刚才复制的内容粘贴到“Key”输入框中,上方的“Tittle”自己随意输入,然后“Add SSH key”

这样事前准备就完成了,嗯,其实就是加一个 SSH 密匙到 Github,这样可以方便后续 Github 项目的同步

2. 创建一个私密 Github 项目

要备份当然首先得有一个 Github 项目啦

直接右上角新建项目

记得选成私密(Private)就行,不然你整个网站就被别人盗走了……

3. 在你的站点目录下初始化你的 Github 项目

进入你的站点所在目录,并执行一系列 git 初始化命令,参考以下代码

假设我的网站在/www/wwwroot/xxx.com,Github 项目为Tsuk1ko/test

cd /www/wwwroot/xxx.com
git init
git remote add origin git@github.com:Tsuk1ko/test.git

第三句的目的是设定当前项目的同步方式为 SSH(是的,我们准备步骤中创建的密匙就是要用在这上面),并指定了仓库地址Tsuk1ko/test

为什么用 SSH 方式而不用 HTTPS 方式?

HTTPS 方式是要你输入用户名密码的,虽然你可以直接将用户名密码输入到链接中,像这样https://yourname:password@github.com/name/project.git,但是在链接中明文输入用户名密码是极不安全的,容易被监听窃取

另外还有一种办法是使用git config --global credential.helper store,这样会在.git中生成一个配置文件来储存你的用户名密码,但是你要意识到你现在所处的目录是一个网站,如果你忘了在网站配置中禁止对.git的访问,那么你的用户名密码也会很容易泄露

所以,SSH 还是最为稳妥的一种方式

4. 尝试同步当前站点到 Github 项目

cd /www/wwwroot/xxx.com
git add -A
git commit -m "backup"
ssh-agent bash
ssh-add /root/github
git push -u origin master

命令解释

  1. 进入网站目录
  2. 把目录下所有文件变化(增、删、改)提交到暂存区
    如果你想只增、改而不删,那么可以用git add .命令代替
  3. 提交所有更改,这个"backup"可以随意填写,没有影响,其实就是你提交改动的时候的说明,但是 commit 的时候必须要有这个说明
  4. 启动 SSH 密钥管理器
  5. 将之前我们创建的github密匙文件添加到密匙管理器中
  6. 推送所有更改到 Github 项目

执行完后你应该能看到文件上传进度等回显,等待执行完毕,然后去自己的私密项目刷新一下,你的网站是不是整个被上传上去了?(好耶!

5. 设定每天自动同步

实际上就是使用 crontab 定时任务每天git push一次,但是操作与上面略有不同,并且有一些需要注意的点

如果你没有安装 crontab,那么百度一下安装方法自行安装,此处不再赘述

当然,如果你使用宝塔面板等自带 crontab 管理功能的就更方便了,接下来的步骤请自行灵性应对

首先找个你喜欢的目录,创建一个脚本例如/root/backup_website.sh,然后写入以下内容并保存

#!/bin/bash
cd /www/wwwroot/xxx.com
git add -A
git commit -m "backup"
ssh-add /root/github
git push -u origin master

接着编辑 crontab 的配置文件,一般是/var/spool/cron/crontabs/root,在最下面加入这行,然后保存退出

30 3 * * * ssh-agent bash /root/backup_website.sh

这条 crontab 命令代表每天凌晨3:30分执行ssh-agent bash /root/backup_website.sh命令

接着重启一下 crontab 使新配置文件生效

# CentOS6 系列及以下
service crond restart
# CentOS7 系列
systemctl restart crond.service
# Ubuntu / Debian 系列
/etc/init.d/cron restart

搞定,这样每天凌晨3:30的时候就会自动备份你的网站到 Github 了,想改成其他时间也可以,自行更改 crontab 命令即可

不过这只是备份了网站目录,数据库之类的也要记得勤备份,或者你也可以仿照这样的方式每天自动把数据库导出到一个地方然后同步到另外一个 Github 项目

注意点解释

细心的你肯定注意到了此步骤和上一步骤中命令的不同,关键就在于ssh-agent

我们是使用 SSH 去同步 git 的,因此在同步之前,服务器上也必须先添加 SSH 密匙(ssh-add)才能连接到 Github

你可以试一下,重开一个 SSH 窗口,直接使用ssh-add /root/github命令,是无法添加密匙的,会报Could not open a connection to your authentication agent.,因为密匙管理器ssh-agent并没有运行

但是如果你使用以下这样的脚本内容

#!/bin/bash
cd /www/wwwroot/xxx.com
git add -A
git commit -m "backup"
ssh-agent bash              #加上这句
ssh-add /root/github
git push -u origin master

然后直接bash /root/backup_website.sh运行,你会发现目录切换到了/www/wwwroot/xxx.com,然后,什么事也没发生

这是为什么呢

因为当你直接运行ssh-agent bash的时候,实际上是相当于使用ssh-agent新建了一个bash窗口,然后……就没有然后了,后面的命令并没有在这个新建的窗口中运行

大概像这样

#!/bin/bash
# 以下命令在原本的 bash 窗口中运行
cd /www/wwwroot/xxx.com
git add -A
git commit -m "backup"

# 当运行到这一句的时候,ssh-agent 新建了一个 bash 窗口
# 而你也看到了这个窗口
ssh-agent bash

# 但是下面这两句仍然是在原本的 bash 窗口中运行的
ssh-add /root/github
git push -u origin master
# 只是因为你执行完 ssh-agent bash 之后,切换到了新的 bash 窗口
# 所以你并不会看到这两句命令执行的回显
# 实际上 ssh-add 将会因为我前面说过的原因而不能添加密匙
# 所以 git push 自然会因为没有密匙而失败

所以我才不在脚本中执行ssh-agent,而是放到了最外层的 crontab 命令上

ssh-agent bash /root/backup_website.sh

这样执行,相当于用ssh-agent创建了一个bash,而这个bash会接收参数/root/backup_website.sh,运行这个脚本,也就是在ssh-agent运行的情况下执行了后续的ssh-add等命令

这样才可以成功实现 SSH 访问 git 并同步

我一开始也是碰到了这个坑,不过弄明白之后感觉对命令行有了更深的理解,总归是没有白忙活