Linux 部署服务器手札 (III)

这几天由于还在准备为客户部署服务器的事情,就顺势再深入学习了一下 Linux,之前的部署,只是可以支持 Django 和各种服务正常在服务器上面跑起来,但是现在的要求是需要把机器放在客户那里无人值守还要好好滴,能够稳定,安全运行,还要保证远程连得上,这样就需要更多的工作。

于是,这次的工作,在之前部署的基础上,更新了 ddns 的部署,增加了自动备份脚本、邮件自动发送等组件。为此我也将鸟哥的私房菜再往后啃了大概 1/4,尝试了使用 vim、shell 脚本以及 crontab 计划任务。

1. ddns 更新

之前用的 python 脚本对于 dnspod 的 ddns 解决方案不算好,实际测试中 python 脚本不间断运行的情况下,我让路由器重新拨号,DHCP 重新分配地址之后,dns 不能正常更新,而且之前的域名和子域名都需要手动查找 id 然后硬编码到了代码里面,不太好用。再者,它的计划运行是放在 python 的进程里面的,万一有个什么情况这个 python 脚本停了,解析就出问题了。这样我就很有风险要跑去客户的工厂帮他维护,这是万万不可的。

然后我又从 dnspod 的官网 api 里面拿来了一个 shell 脚本,直接拿来用了:

这个只是单次更新,因此我们还需要调度系统一段时间执行一次来更新域名的 a 记录。

额外记录一下,如果需要直接使用 ./xxx.sh 来运行一个 shell 脚本,就必须拥有 xxx.sh 这个脚本文件的 x 执行权限,如果默认创建一个文本文件的时候权限是 644 是不可以这样的,必须手动 chomod 一下。

2. crontab 任务计划

由于我们现在需要定时执行一些任务(一个是动态 dns 更新,另一个是备份),因此我们需要用到 crontab 这个模块。

在 shell 里面输入 crontab -e。

第一次打开的时候可能会需要选择编辑器,用 vim 就好了。

然后该用户的任务计划配置文件会被打开,下面每加一条记录就是增加了一个任务计划:

每条记录有六个参数:

[分钟] [小时] [天] [月] [星期] [命令]

前面五个是计划的时间段,格式为 [指定日期]/[间隔]

指定日期可以是:

  1. * 代表任意
  2. a-b 表示 a 到 b 时间或日期的区间内执行
  3. a 表示某一个时间或日期

其中,数字的取值范围为:

  1. 分钟:0-59
  2. 小时:0-23
  3. 日期:1-31
  4. 月份:1-12
  5. 星期:0-6(0 代表星期天)

那么我既然要每分钟检查一次动态域名,那么我的配置是:

*/1 * * * * /var/ddns/ddns.sh >> /var/ddns/ddns.log

注意我这里把输出流重定向了一个日志文件。

3. 自动备份

这个以前也做过,不过这次在 linux 下,大同小异,直接放脚本:

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

dt=$(date +%Y%m%d)
cd /var/backup
rm -rf $dt
mkdir $dt
cd $dt

# 1. /etc
cp -r /etc/apache2 ./

# 2. /var/django
cp -r /var/django ./

# 3. backup db
mysqldump -uroot -p******** mydb > mydb.sql

# 4. compress
cd ..
chmod -R 777 $dt
tar -jpcv -f backup_$dt.tar.bz2 $dt/
rm -rf $dt/

# 5. mail
python3 pymail.py "yc.easecloud.cn backup_$dt" backup_$dt.tar.bz2

过程只是简单地复制源码,备份数据库,打包,发邮件。

至于发邮件的环节,以前已经做过,由于直接用 shell 发邮件一时间没研究通,还是沿用了以前的 python 脚本,运行正常。

# pymail.py
import smtplib
import sys
import os
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email import encoders

def send_mail(to_list, sub, content):
    me=mail_user+"<"+mail_user+"@"+mail_postfix+">"
    msg = MIMEMultipart('related')
    msg['Subject'] = sub
    msg['From'] = me
    msg['To'] = to_list
    msg.attach(MIMEText(content, 'plain'))
    for att_path in attaches:
        if os.path.exists(att_path):

            fp = open(att_path, 'rb')
            attach = MIMEBase('application', "octet-stream")
            attach.set_payload(fp.read())
            fp.close()
            encoders.encode_base64(attach)
            basename=os.path.basename(att_path)
            attach.add_header("Content-Disposition","attachment",filename=basename)
            msg.attach(attach)
            continue

            fname = os.path.basename(att_path)
            attach = MIMEText(open(att_path, 'rb').read(), 'base64', 'utf-8')
            attach["Content-Type"] = 'application/octet-stream'
            attach.add_header("Content-Disposition", "attachment", filename = fname)
            msg.attach(attach)
    try:
        s = smtplib.SMTP()
        s.connect(mail_host)
        s.login(mail_user,mail_pass)
        #print(msg.as_string())
        s.sendmail(me, to_list, msg.as_string())
        s.close()
        print('The mail was sent successfully!')
        return True
    except Exception as e:
        print('It seemed some error occured.')
        print(str(e))
        return False

"""
Configuration part
"""

# sender configuration
mail_host="smtp.163.com"
mail_user="backup"
mail_pass="********"
mail_postfix="163.com"

# attachment list
attaches = (
    # 在参数中指定附件
    sys.argv[2],
    )

# target emails
receivers = (
    'backup@163.com',
    )

# action
if __name__ == '__main__':
    for rcv in receivers:
        print('Attempting to send to %s' % rcv)
        subj = 'my backup'
        if len(sys.argv) > 1: subj = sys.argv[1]
        send_mail(rcv, subj, 'server backup')

【转载请附】愿以此功德,回向 >>

原文链接:https://www.huangwenchao.com.cn/2014/04/linux-deploy-3.html【Linux 部署服务器手札 (III)】

发表评论

电子邮件地址不会被公开。 必填项已用*标注