1. 程式人生 > >基於 Python + Proftpd 實現文件自動備份

基於 Python + Proftpd 實現文件自動備份

centos project ase getcwd upa roo 執行 http proftpd

一、環境概述

1.概述

作用:將項目服務器的重要需備份文件自動定期備份至公司內部的服務器

架構:FTP 服務器部署於內網服務器,為被動模式,通過防火墻映射21端口和通信端口,使外網的機器可以訪問。客戶端為Linux或Windows服務器,通過python腳本(版本為python 2)將本地需要備份的文件定時打包上傳至 FTP 服務器

2.服務器配置說明

角色 操作系統 IP 地址 備註
備份客戶端 centos 6/7、Windows 192.168.101-103
FTP 服務器 centos 7.4 192.168.1.9 使用 ftp 軟件為 proftpd

二、proftpd 服務器部署

1.EPEL 安裝

[root@localhost ~]# rpm -ivh http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm

2.proftpd 與 OpenSSL 安裝

[root@localhost ~]# yum install -y proftpd openssl proftpd-utils

3.啟動proftpd服務

[root@localhost ~]# systemctl start proftpd.service
[root@localhost ~]# systemctl enable proftpd.service

4.防火墻設置

[root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=ftp
[root@localhost ~]# firewall-cmd --reload

5.ftp用戶創建

[root@localhost ~]# groupadd ftpgroup
## 設置 /ftpshare 目錄為 proftpd 用戶的家目錄
[root@localhost ~]# useradd -G ftpgroup proftpd -s /sbin/nologin -d /ftpshare
[root@localhost ~]# passwd proftpd

6.proftpd 服務器配置

[root@localhost ~]# cp /etc/proftpd.conf /etc/proftpd.conf.bak
[root@localhost ~]# vi /etc/proftpd.conf
## 設置被動模式端口為 6000-6100
PassivePorts 6000 6100
## 設置被動模式返回地址為映射的公網地址
MasqueradeAddress xxx.xxx.xxx.xxx
## 設置超時時間為 600
TimeoutIdle 600

7.防火墻開放通信端口

[root@localhost ~]# firewall-cmd --permanent --zone=public --add-port=6000-6100/tcp
[root@localhost ~]# firewall-cmd --reload

8.重啟服務

[root@localhost ~]# systemctl restart proftpd.service

三、客戶端配置

1.Linux 服務器配置

1.1 創建ftp備份腳本
[root@localhost ~]# cat /opt/backup_to_ftp_for_linux.py 

#!/usr/bin/python
# _*_ coding: utf-8 _*_
# CREATE DATE:2018/10/27
# AUTHOR: Liuzy
# 腳本作用:
## 1.將ftp提供下載的文件下載至本地
## 2.將本地需要備份的文件打包上傳至ftp服務器的備份目錄下

import shutil, os, datetime, zipfile, sys,  socket
from ftplib import FTP

# 定義當前時間格式
time = datetime.datetime.now()
ytime = time + datetime.timedelta(days=-1)
nowtime = datetime.datetime.now().strftime("%Y%m%d")
yestime = ytime.strftime("%Y%m%d")
# 運行腳本的服務器地址
localhost = ‘xxx.xxx.xxx.xxx‘
# 服務器需要備份的文件列表
backupfiledir = ["/dbbackup/evedayback/",
                 "/dbbackup/eveweekback/"]
backupfiledirname = [yestime+"_table", yestime+"_database"]
# 備份所需信息,包括ftp服務器地址、端口、備份ftp用戶名、密碼
backupinfo = ["xxx.xxx.xxx.xxx", 21, "proftpd", "Password123"]
# 定義備份文件存放文件夾的名稱格式
backupdirname = localhost + ‘_‘ + yestime + ‘_‘ + "backupfile"

class ftpserver:
    def __init__(self, host, port, username, password, localpath):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.localpath = localpath

    def connect(self):
        ftp = FTP()
        ftp.connect(self.host, self.port)
        ftp.login(self.username, self.password)
        return ftp

    def backupfile(self):
        bufsize = 1024
        # 嘗試創建備份文件存放文件夾
        try:
            os.mkdir(backupdirname)
        except Exception as e:
            print("目錄 %s 已存在" % backupdirname)
        # 拷貝備份文件所在文件夾至指定文件夾
        bcd = os.getcwd()+os.sep+backupdirname+"/"+yestime+"/"
        try:
            shutil.copytree(backupfiledir[0]+backupfiledirname[0], bcd+backupfiledirname[0])
        except OSError:
            print("目錄不存在")
        try:
            shutil.copytree(backupfiledir[1]+backupfiledirname[1], bcd+backupfiledirname[1])
        except OSError:
            print("目錄不存在")
        print("拷貝文件夾 %s 至目錄 %s" % (backupfiledirname, backupdirname))
        # 壓縮備份文件夾
        filelist = []
        backupzipname = backupdirname+‘.tar‘
        if os.path.isfile(backupdirname):
            filelist.append(backupdirname)
        else:
            for root,dirs,files in os.walk(backupdirname):
                for name in files:
                    filelist.append(os.path.join(root,name))
        zf = zipfile.ZipFile(backupzipname,"w",zipfile.ZIP_DEFLATED,allowZip64=True)
        for tar in filelist:
            arcname = tar[len(backupdirname):]
            zf.write(tar,arcname)
        zf.close()
        # 連接ftp服務器,備份文件
        ftp = ftpserver.connect(self)
        try:
            ftp.mkd(localhost)
        except Exception as e:
            print("目錄 %s 已存在" % localhost)
        fp = open(backupzipname, ‘rb‘)
        print("開始備份文件 %s ... " % backupzipname)
        ftp.storbinary(‘STOR ‘ + localhost + ‘/‘ +  backupzipname, fp, bufsize)
        ftp.set_debuglevel(0)
        fp.close()
        print("成功備份文件 %s 至服務端 %s" % (backupzipname, localhost + ‘/‘ + backupzipname))
        ftp.quit()
        # 刪除存放備份文件的臨時文件夾與壓縮包
        try:
            os.unlink(backupzipname)
            shutil.rmtree(backupdirname)

        except Exception as e:
            print(e)

backup = ftpserver(backupinfo[0], backupinfo[1], backupinfo[2], backupinfo[3], "")
backup.backupfile()
1.2 創建啟動 python腳本的 shell 腳本
[root@localhost ~]# cat /opt/backup_ftp.sh
#!/bin/bash
## set backup python scripts path
PY_HOME=/opt/

cd $PY_HOME
nohup ./backup_to_ftp_for_linux.py >/dev/null 2>&1 &
1.3 根據實際需求將腳本加入定時任務
[root@localhost ~]# crontab -e
0 2 * * * /opt/backup_ftp.sh

2.windows 客戶端配置

2.1 編寫備份 python 腳本
#!/usr/bin/env python
# _*_ coding: utf-8 _*_
# CREATE DATE:2018/10/27
# AUTHOR: Liuzy
# 腳本作用:
## 1.將ftp提供下載的文件下載至本地
## 2.將本地需要備份的文件打包上傳至ftp服務器的備份目錄下

import shutil, os, datetime, zipfile, sys, socket
from ftplib import FTP

# 定義當前時間
time = datetime.datetime.now()
ytime = time + datetime.timedelta(days=-1)
nowtime = datetime.datetime.now().strftime("%Y%m%d")
yestime = ytime.strftime("%Y%m%d")
# 運行腳本的服務器地址
localhost = socket.gethostbyname(socket.gethostname())
# 服務器需要備份的文件列表
backupfiledir = ["D:/dbbackup/evedayback/",
                 "D:/dbbackup/eveweekback/"]
backupfiledirname = [yestime+"_table", yestime+"_database"]
# 備份所需信息,包括ftp服務器地址、端口、備份ftp用戶名、密碼
backupinfo = ["xxx.xxx.xxx.xxx", 21, "proftpd", "Password123"]
# 定義備份文件存放文件夾的名稱格式
backupdirname = localhost + ‘_‘ + yestime + ‘_‘ + "backupfile"

class ftpserver:
    def __init__(self, host, port, username, password, localpath):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.localpath = localpath

    def connect(self):
        ftp = FTP()
        ftp.connect(self.host, self.port)
        ftp.login(self.username, self.password)
        return ftp

    def backupfile(self):
        bufsize = 1024

        # 嘗試創建備份文件存放文件夾
        try:
            os.mkdir(backupdirname)
        except Exception as e:
            print("目錄 %s 已存在" % backupdirname)

        # 拷貝備份文件所在文件夾至指定文件夾
        bcd = os.getcwd()+os.sep+backupdirname+"/"+yestime+"/"
        try:
            shutil.copytree(backupfiledir[0]+backupfiledirname[0], bcd+backupfiledirname[0])
        except IOError:
            print("目錄不存在")
        except WindowsError:
            print("目錄不存在")
        try:
            shutil.copytree(backupfiledir[1]+backupfiledirname[1], bcd+backupfiledirname[1])
        except IOError:
            print("目錄不存在")
        except WindowsError:
            print("目錄不存在")
        print("拷貝文件夾 %s 至目錄 %s" % (backupfiledirname, backupdirname))

        # 壓縮備份文件夾
        filelist = []
        backupzipname = backupdirname+‘.tar‘
        if os.path.isfile(backupdirname):
            filelist.append(backupdirname)
        else:
            for root,dirs,files in os.walk(backupdirname):
                for name in files:
                    filelist.append(os.path.join(root,name))
        zf = zipfile.ZipFile(backupzipname,"w",zipfile.ZIP_DEFLATED,allowZip64=True)
        for tar in filelist:
            arcname = tar[len(backupdirname):]
            zf.write(tar,arcname)
        zf.close()

        # 連接ftp服務器,備份文件
        ftp = ftpserver.connect(self)
        try:
            ftp.mkd(localhost)
        except Exception as e:
            print("目錄 %s 已存在" % localhost )
        fp = open(backupzipname, ‘rb‘)
        print("開始備份文件 %s ... " % backupzipname)
        ftp.set_debuglevel(2)
        try:
            ftp.storbinary(‘STOR ‘ + localhost + ‘/‘ +  backupzipname, fp, bufsize)
        except:
            print("error")
        # ftp.set_pasv(0)
        ftp.set_debuglevel(0)
        fp.close()
        print("成功備份文件 %s 至服務端 %s" % (backupzipname, localhost + ‘/‘ + backupzipname))
        ftp.quit()

        # 刪除存放備份文件的臨時文件夾與壓縮包
        try:
            os.unlink(backupzipname)
            shutil.rmtree(backupdirname)

        except Exception as e:
            print(e)

backup = ftpserver(backupinfo[0], backupinfo[1], backupinfo[2], backupinfo[3], "")
backup.backupfile()
2.2 使用 pyinstaller 打包腳本為可執行 exe
2.3 將可執行 exe 加入客戶端任務計劃程序

基於 Python + Proftpd 實現文件自動備份