在 MacOS 及 AWS 上部署 supervisor

部署 supervisor

前言

本篇重點如下:

  1. 在 Mac OS 上安裝並部署 Supervisor
  2. 在 AWS 上安裝並部署 Supervisor

Supervisor是什麼?

Supervisor 是一套程序管理系統。因為 Ray 的專案有使用到 Laravel 的 queue ,而 queue 必須要常駐在背景執行,那要是不小心失敗或中斷了怎麼辦呢? supervisor 可以確保當 queue 失敗中斷時,自動地幫我們重啟。

Mac OS

安裝

  • 安裝 Supervisor
    brew install supervisor

配置

  • 進到預設設定檔

    vim /usr/local/etc/supervisord.ini
  • 更改預設 include 目錄,到最後一行,修改如下

    [include]
    files = /usr/local/etc/supervisor.d/*.conf
  • 新增客製化配置目錄及檔案

    mkdir /usr/local/etc/supervisor.d;
    vim /usr/local/etc/supervisor.d/processNameYouLike.conf;
  • 輸入下面的設定

    [program:programNameYouLike]
    process_name=%(program_name)s_%(process_num)02d
    command=php absoluteAddressOfYourProject/artisan queue:work sqs --sleep=3 --tries=3 --daemon
    autostart=true
    autorestart=true
    user=ray
    numprocs=8
    redirect_stderr=true
    stdout_logfile=/absoluteAddressOfLocationYouWouldLikeToPutTheLog/worker.log

啟動

  • 啟動服務

    sudo supervisord -c /usr/local/etc/supervisord.ini
  • 進到控制台

    sudo supervisorctl -c /usr/local/etc/supervisord.ini
  • 更新配置

    update
  • 查看狀態

    status

看起來如下:

AWS

Amazon Linux 2 AMI

本篇記錄使用的AWS型號如下:

  • Amazon Linux 2 AMI (HVM), SSD Volume Type - ami-0f9ae750e8274075b
  • t2.micro (Variable ECUs, 1 vCPUs, 2.5 GHz, Intel Xeon Family, 1 GiB memory, EBS only)

安裝

  • 安裝 supervisor
    sudo yum install -y supervisor

配置

  • 到預設設定檔

    sudo vim /etc/supervisord.conf
  • 更改最後一行 include 的目錄

    [include]
    files = supervisord.d/*.conf
  • 新增配置檔,如果資料夾不存在就創建

    sudo mkdir /etc/supervisord.d;
    sudo vim /etc/supervisord.d/projectFileNameYouLike.conf
  • 新增配置

    [program:laravel-worker]
    process_name=%(program_name)s_%(process_num)02d
    command=sudo php absoluteAddressOfYourProject/artisan queue:work sqs --sleep=3 --tries=3 --daemon
    autostart=true
    autorestart=true
    user=root
    numprocs=8
    redirect_stderr=true
    stdout_logfile=absoluteAddressOfYourProject/worker.log

啟動

  • 啟動 supervisor

    sudo supervisord -c /etc/supervisord.conf
  • 套用新的配置檔並查看狀態

    sudo supervisorctl update;
    sudo supervisorctl status

配置自動重啟

  • 增加重啟配置檔

    sudo vim /etc/init.d/supervisord
  • 輸入以下配置

    #! /bin/sh
    ### BEGIN INIT INFO
    # Provides: supervisord
    # Required-Start: $remote_fs
    # Required-Stop: $remote_fs
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Short-Description: Example initscript
    # Description: This file should be used to construct scripts to be
    # placed in /etc/init.d.
    ### END INIT INFO

    # Author: Dan MacKinlay <danielm@phm.gov.au>
    # Based on instructions by Bertrand Mathieu
    # http://zebert.blogspot.com/2009/05/installing-django-solr-varnish-and.html

    # Do NOT "set -e"

    # PATH should only include /usr/* if it runs after the mountnfs.sh script
    PATH=/sbin:/usr/sbin:/bin:/usr/bin
    DESC="Description of the service"
    NAME=supervisord
    DAEMON=/usr/local/bin/supervisord
    DAEMON_ARGS=""
    PIDFILE=/var/run/$NAME.pid
    SCRIPTNAME=/etc/init.d/$NAME

    # Exit if the package is not installed
    [ -x "$DAEMON" ] || exit 0

    # Read configuration variable file if it is present
    [ -r /etc/default/$NAME ] && . /etc/default/$NAME

    # Load the VERBOSE setting and other rcS variables
    . /lib/init/vars.sh

    # Define LSB log_* functions.
    # Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
    . /lib/lsb/init-functions

    #
    # Function that starts the daemon/service
    #
    do_start()
    {
    # Return
    # 0 if daemon has been started
    # 1 if daemon was already running
    # 2 if daemon could not be started
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
    || return 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
    $DAEMON_ARGS \
    || return 2
    # Add code here, if necessary, that waits for the process to be ready
    # to handle requests from services started subsequently which depend
    # on this one. As a last resort, sleep for some time.
    }

    #
    # Function that stops the daemon/service
    #
    do_stop()
    {
    # Return
    # 0 if daemon has been stopped
    # 1 if daemon was already stopped
    # 2 if daemon could not be stopped
    # other if a failure occurred
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently. A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
    }

    #
    # Function that sends a SIGHUP to the daemon/service
    #
    do_reload() {
    #
    # If the daemon can reload its configuration without
    # restarting (for example, when it is sent a SIGHUP),
    # then implement that here.
    #
    start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    return 0
    }

    case "$1" in
    start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    do_start
    case "$?" in
    0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
    stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    do_stop
    case "$?" in
    0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
    #reload|force-reload)
    #
    # If do_reload() is not implemented then leave this commented out
    # and leave 'force-reload' as an alias for 'restart'.
    #
    #log_daemon_msg "Reloading $DESC" "$NAME"
    #do_reload
    #log_end_msg $?
    #;;
    restart|force-reload)
    #
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    #
    log_daemon_msg "Restarting $DESC" "$NAME"
    do_stop
    case "$?" in
    0|1)
    do_start
    case "$?" in
    0) log_end_msg 0 ;;
    1) log_end_msg 1 ;; # Old process is still running
    *) log_end_msg 1 ;; # Failed to start
    esac
    ;;
    *)
    # Failed to stop
    log_end_msg 1
    ;;
    esac
    ;;
    *)
    #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    exit 3
    ;;
    esac

    :

    script來源

  • 增加權限

    sudo chmod +x /etc/init.d/supervisord
  • 將新增的開機重啟配置檔加到系統

    sudo chkconfig --add supervisord
  • 打開自動重啟功能,並開始

    sudo chkconfig supervisord on;
    sudo service supervisord start

    Amazon Linux 2 AMI

    型號:

  • Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type - ami-00a5245b4816c38e6

安裝

  • 安裝 supervisor

    sudo easy_install supervisor
  • /usr/local/bin 加到 sudo path

    sudo vim /etc/sudoers
    Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

配置

  • 建立設定檔

    sudo su -
    sudo echo_supervisord_conf > /etc/supervisord.conf;
    sudo vim /etc/supervisord.conf
  • 更改最後一行 include 的目錄

    [include]
    files = /etc/supervisord.d/*.conf
  • 新增配置檔,如果資料夾不存在就創建

    sudo mkdir /etc/supervisord.d;
    sudo vim /etc/supervisord.d/projectFileNameYouLike.conf
  • 新增配置

    [program:laravel-worker]
    process_name=%(program_name)s_%(process_num)02d
    command=php absoluteAddressOfYourProject/artisan queue:work sqs --sleep=3 --tries=3 --daemon
    autostart=true
    autorestart=true
    user=apache
    numprocs=8
    redirect_stderr=true
    stdout_logfile=absoluteAddressOfYourProject/worker.log

啟動

  • 啟動 supervisor

    sudo supervisord -c /etc/supervisord.conf
  • 套用新的配置檔並查看狀態

    sudo supervisorctl update;
    sudo supervisorctl status

配置自動重啟

  • 增加重啟配置檔

    sudo vim /etc/init.d/supervisord
  • 輸入以下配置

    #!/bin/bash
    #
    # supervisord Startup script for the Supervisor process control system
    #
    # Author: Mike McGrath <mmcgrath@redhat.com> (based off yumupdatesd)
    # Jason Koppe <jkoppe@indeed.com> adjusted to read sysconfig,
    # use supervisord tools to start/stop, conditionally wait
    # for child processes to shutdown, and startup later
    # Erwan Queffelec <erwan.queffelec@gmail.com>
    # make script LSB-compliant
    #
    # chkconfig: 345 83 04
    # description: Supervisor is a client/server system that allows \
    # its users to monitor and control a number of processes on \
    # UNIX-like operating systems.
    # processname: supervisord
    # config: /etc/supervisord.conf
    # config: /etc/sysconfig/supervisord
    # pidfile: /var/run/supervisord.pid
    #
    ### BEGIN INIT INFO
    # Provides: supervisord
    # Required-Start: $all
    # Required-Stop: $all
    # Short-Description: start and stop Supervisor process control system
    # Description: Supervisor is a client/server system that allows
    # its users to monitor and control a number of processes on
    # UNIX-like operating systems.
    ### END INIT INFO

    # Source function library
    . /etc/rc.d/init.d/functions

    # Source system settings
    if [ -f /etc/sysconfig/supervisord ]; then
    . /etc/sysconfig/supervisord
    fi

    # Path to the supervisorctl script, server binary,
    # and short-form for messages.
    supervisorctl=/usr/local/bin/supervisorctl
    supervisord=${SUPERVISORD-/usr/local/bin/supervisord}
    prog=supervisord
    pidfile=${PIDFILE-/tmp/supervisord.pid}
    lockfile=${LOCKFILE-/var/lock/subsys/supervisord}
    STOP_TIMEOUT=${STOP_TIMEOUT-60}
    OPTIONS="${OPTIONS--c /etc/supervisord.conf}"
    RETVAL=0

    start() {
    echo -n $"Starting $prog: "
    daemon --pidfile=${pidfile} $supervisord $OPTIONS
    RETVAL=$?
    echo
    if [ $RETVAL -eq 0 ]; then
    touch ${lockfile}
    $supervisorctl $OPTIONS status
    fi
    return $RETVAL
    }

    stop() {
    echo -n $"Stopping $prog: "
    killproc -p ${pidfile} -d ${STOP_TIMEOUT} $supervisord
    RETVAL=$?
    echo
    [ $RETVAL -eq 0 ] && rm -rf ${lockfile} ${pidfile}
    }

    reload() {
    echo -n $"Reloading $prog: "
    LSB=1 killproc -p $pidfile $supervisord -HUP
    RETVAL=$?
    echo
    if [ $RETVAL -eq 7 ]; then
    failure $"$prog reload"
    else
    $supervisorctl $OPTIONS status
    fi
    }

    restart() {
    stop
    start
    }

    case "$1" in
    start)
    start
    ;;
    stop)
    stop
    ;;
    status)
    status -p ${pidfile} $supervisord
    RETVAL=$?
    [ $RETVAL -eq 0 ] && $supervisorctl $OPTIONS status
    ;;
    restart)
    restart
    ;;
    condrestart|try-restart)
    if status -p ${pidfile} $supervisord >& /dev/null; then
    stop
    start
    fi
    ;;
    force-reload|reload)
    reload
    ;;
    *)
    echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload}"
    RETVAL=2
    esac

    exit $RETVAL

    script來源

  • 增加權限

    sudo chmod +x /etc/init.d/supervisord
  • 將新增的開機重啟配置檔加到系統

    sudo chkconfig --add supervisord
  • 打開自動重啟功能,並開始

    sudo chkconfig supervisord on;
    sudo service supervisord start
  • 在設定好配置檔之前,如何關閉 supervisord ?

    ps -ef | grep supervisord
    kill -s SIGTERM 29646

結論

完成設定後,每次 reboot , AWS 就會自動地重啟 supervisor

使用 Laravel Queue 以及 AWS SQS 伸縮自如的 git flow

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×