在实际项目中,我们不可避免的需要用到自动化脚本来帮助我们完成一些事情,比如自动发送邮件,当系统宕机之后自动重启等等。下面我将结合一个实际项目分析介绍,总共在哪些场景中使用了自动化脚本并且是如何做的。

前言

在这个项目中,我们除了完成构建系统的基本代码之外,还需要完成下面一些任务:

  1. 定时进行数据处理并入库
  2. 定时使用casperjs截图,并发送邮件
  3. 监控是否有新代码提交,更新代码,并重启系统
  4. 为了保证顺利截图,还需要创建守护进程

crontab命令

  • 分析上面的一些任务,我们发现基本都有定时两个字,那么在linux中这个具体是怎么实现的呢。就是使用crontab命令来完成定时任务。(这里暂且先不做关于crontab具体介绍和使用的过多介绍,仅介绍在实际中是如何操作的)
  • crontab -e编辑crontab列表;crontab -l查看crontab列表。
  • 它执行任务的最小间隔是1min,利用这个特性,我们可以用来创建守护进程。即,如果发现某个进程不存在,即立即重新运行。
  • 需要注意的是,crontab命令在执行时,往往并不知道这个命令是在什么样的环境下执行的。所以,对于执行命令,我们往往都写成命令的绝对路径,比如/usr/local/bin/node
  • 我们还可以在指定路径下,执行命令。比如:

    1
    * * * * * (cd /sotraffic-web/webpack; sh ./../crontabscript/daemon.sh >> ./../log/daemon.log)
  • 任意一个在命令行执行的命令都可以被创建成crontab定时任务。

选取脚本语言

  • node
    这里隆重介绍下node中的child_process = require('child_process')模块,利用child_process中的exec方法,我们可以执行命令行中可执行的任意命令,比如:cd path && ls 或者git pullpm2 restart等等

  • shell, python
    关于shell语法的介绍,可以参考这个系列

  • 针对前言提到的4个任务,我们都分别采用了什么脚本语言呢?

  1. 定时进行数据处理并入库 (node)
  2. 监控是否有新代码提交,更新代码,并重启系统 (node)

  3. 定时使用casperjs截图,并发送邮件 (casperjs, python, shell)
    实际上这一步骤,是两个任务的结合,先用casperjs完成截图,并且截图完成后,再执行使用python编写的发送邮件脚本(实际上node也可以)。而结合的这一任务是用shell来写的。
    在这一步骤中还遇到一个问题,就是由于未知原因,截图不能一次性成功。检测截图是否成功,如果不成功则继续执行命令,直到成功为止。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #!/bin/bash
    echo "====Starting capturing and sending Email===="
    echo `date +%Y-%m-%d%t%H:%M:%S`
    source /etc/bashrc
    TIME=`date +%Y-%m-%d`
    myFilePc="/www/static/img/$TIME/report_pc.png"
    myFileMobile="/www/static/img/$TIME/report_mobile.png"
    if [ -f $myFilePc ]
    then
    rm -f "$myFilePc"
    echo "rm $myFilePc is done!"
    else
    echo "cannot find $myFilePc"
    fi
    if [ -f $myFileMobile ]
    then
    rm -f "$myFileMobile"
    echo "rm $myFileMobile is done!"
    else
    echo "cannot find $myFileMobile"
    fi
    #需要检测哪个图没有截取成功,再次执行命令,所以把capture_pc和capture_mobile分成两个文件写,这样成本最低
    while [ ! -f $myFilePc ]
    do
    /usr/local/bin/casperjs /crontabscript/capture_pc.js
    done
    while [ ! -f $myFileMobile ]
    do
    /usr/local/bin/casperjs /crontabscript/capture_mobile.js
    done
    /usr/local/Python-2.7.11/python /crontabscript/Email.py
    echo ""
  4. 为了保证顺利截图,还需要创建守护进程 (shell)
    创建守护进行的思路是,每隔1分钟检查一次查找所需进程是否在进程列表中,如果没有,则启动进程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/bin/bash
    CONDITION='能识别进程的关键字'
    CMD='需要执行的命令'
    PROCESS_INFO=`ps aux|grep $CONDITION|grep -v 'grep'`
    #echo $PROCESS_INFO
    PID=`echo "$PROCESS_INFO"|awk '{print $2}'`
    #echo $PID
    if [ "$PID" == "" ]
    then
    TIME=`date`
    echo "=============$TIME==============="
    echo 'No runnning process found! Try starting new process...'
    `$CMD`
    echo 'Restart done!'
    fi

记录日志

因为这些脚本会定时自动执行,在执行过程中可能会失败,我们需要一些信息来帮助我们定位问题。所以一定要在脚本中输出一些有价值的信息,并记录日志。

遇到过的问题

  • python在发送邮件时,使用域名致使邮件不能成功发送,暂时使用IP。(原因待查)
  • crontab执行截图时,报出phantomjs未安装,以及python未找到的错误。
    原因:crontab未找到正确的环境变量
    解决: 在脚本中执行截图操作前,先source /etc/bashrc
  • 重启webpack的命令需要在指定的路径下才能执行

    解决:(1)先cd到指定路径,再执行命令。(2)或者命令中指定webpack.config.js
    1
    /usr/local/bin/node /webpack/node_modules/.bin/webpack-dev-server /webpack/webpack.config.js --inline --hot --quiet --host 0.0.0.0 --port 8366

感想

自我感想,无论是使用shell、python、node,或者php都是可以完成任务的,没有规定什么样的语言只能完成什么样的任务。个人更建议选择一种自己熟悉的语言,来完成所有操作,这样可以降低学习成本。