如何将循环Bash脚本作为服务运行?

时间:2014-01-20 17:00:26

标签: linux bash amazon-ec2

我有两个运行HAProxy的Amazon Linux EC2实例。我想监视来自另一个实例的每个实例,如果实例变得不可用,另一个实例将发出API命令以将弹性IP移动到活动服务器。

我创建了一个Bash脚本,每隔XX秒进行一次监控。我需要将脚本设置为作为服务运行,因此我创建了一个服务包装器,并根据我找到并注册为服务的模板放置在/etc/init.d中。

问题是当我发出命令#service hamonitor start时,它说“启动hamonitor ...”,但我从未看到OK消息,如果我发出stop命令,它会失败,如果我发出status命令,它说它没有运行。但是,如果我检查日志,则表明该脚本实际上正在运行。我假设我需要一个合适的PID文件和/或由于脚本在无限循环中运行,它永远不会完成所以OK不会被发出。

服务包装:

#!/bin/sh
#
# /etc/init.d/hamonitor
# Subsystem file for "hamonitor" server
#
# chkconfig: 2345 95 05 (1)
# description: hamonitor server daemon
#
# processname: hamonitor

### BEGIN INIT INFO
# Provides: 
# Required-Start: 
# Required-Stop: 
# Should-Start: 
# Should-Stop: 
# Default-Start: 
# Default-Stop: 
# Short-Description: 
# Description:      
### END INIT INFO

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

PROG=hamonitor
EXEC=/etc/haproxy/hamonitor
LOCKFILE=/var/lock/subsys/$prog
PIDFILE=/var/run/$prog.pid
RETVAL=0

start() {
    echo -n $"Starting $PROG:"
    echo
    #daemon $EXEC &
    /etc/haproxy/hamonitor &
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
      touch LOCKFILE
      touch PIDFILE
      echo "[ OK ]"
    else
      echo "[ FAIL: ${retval} ]"
    fi
    return $RETVAL
}

stop() {
    echo -n $"Stopping $PROG:"
    echo 
    killproc $PROG -TERM
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
      rm -f LOCKFILE
      rm -f PIDFILE
      echo "[ OK ]"
    else
      echo "[ FAIL: ${RETVAL} ]"
    fi
    return $RETVAL
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status $PROG
        RETVAL=$?
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo $"Usage: $0 {start|stop|status|restart}"
    RETVAL=1
esac

exit $RETVAL

应用:

#!/usr/bin/env bash

export EC2_HOME=/opt/aws/apitools/ec2
export JAVA_HOME=/usr/lib/jvm/jre

AWS_ACCESS_KEY="XXXXXXXXXXXXXXXXXXXXXXXXX"
AWS_SECRET_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
VIP1="1.2.3.4"
VIP1_ALLOCATIONID="eipalloc-XXXXXXX"
THIS_NODE_EC2_ID="i-XXXXXXX"
THIS_NODE_PRIVATE_IPADDRESS1="10.60.0.11" 
THIS_NODE_HEALTHCHECK_URL="http://10.60.0.10/haproxy?monitor"
OTHER_NODE_HEALTHCHECK_URL="http://10.60.49.50/haproxy?monitor"
CHECK_OTHER_INTERVAL=5
CHECK_OTHER_FAIL_COUNT=0
CHECK_OTHER_RUN_COUNT=0
AFTER_TAKEOVER_WAIT=30

function takeover_vips {
  /opt/aws/bin/ec2-associate-address -aws-access-key ${AWS_ACCESS_KEY} -aws-secret-key ${AWS_SECRET_KEY} -a ${VIP1_ALLOCATIONID} -i ${THIS_NODE_EC2_ID} -private-ip-address ${THIS_NODE_PRIVATE_IPADDRESS1} -allow-reassociation > /dev/null
}

function does_this_node_have_ips {
  is_active=$(/opt/aws/bin/ec2-describe-addresses -aws-access-key ${AWS_ACCESS_KEY} -aws-secret-key ${AWS_SECRET_KEY}  | grep ${VIP1} | grep ${THIS_NODE_EC2_ID})
  if [ "$is_active" = "" ]; then
    echo "no"
  else
    echo "yes"
  fi
}

function log_msg {
  msg=$1
  msg="$(date) -- ${msg}"
  echo ${msg} >> /var/log/hamonitorlog
}

while [ . ]; do
    healthcheck_response=$(curl -sL -w "%{http_code}" ${OTHER_NODE_HEALTHCHECK_URL} -o /dev/null) 
    if [ "$healthcheck_response" != "200" ]; then
        CHECK_OTHER_FAIL_COUNT=$((CHECK_OTHER_FAIL_COUNT+1))
        if [ "$CHECK_OTHER_FAIL_COUNT" -gt 2 ]; then
          takeover_vips
          CHECK_OTHER_FAIL_COUNT=0
          sleep ${AFTER_TAKEOVER_WAIT}
        fi
    sleep ${CHECK_OTHER_INTERVAL}
done

1 个答案:

答案 0 :(得分:3)

某些Linux发行版有up-start和其他init;我假设你有initchkconfig用于维护符号链接。你应该确认评论,

# chkconfig: 2345 95 05 (1)

对您的系统是正确的。

作为猜测,您需要通过脚本调用daemon。这可能是某些init脚本库中的脚本函数,如 /etc/rc.d/init.d/functions 。我建议您使用daemon()函数(如果存在)。或者,

  daemon $EXEC &                                               #option1
  nohup /etc/haproxy/hamonitor < /dev/null > /dev/null 2>&1 &  #option2
  /etc/haproxy/hamonitor&                                      #option3, 2 lines.
  disown $!                                                    #...

这与SIGCHLD和流程返回状态有关(有关详情,请参阅man wait)。同样,您可能需要从控制终端分离hamonitor。在这种情况下,您可以使用logger向系统日志发送信息;我想 App 脚本是hamonitor代码?只需将echo更改为logger

如果hamonitor需要 stdout stdin 和/或 stderr ,您可能需要重定向到其他文件如果它需要它。如果是这种情况,您也可以考虑通过screen运行它。

修改:最后一个选项可用于创建正确的PIDFILE。例如,

  # !!! optional grabbing of lock here...
  /etc/haproxy/hamonitor &   # spawn in bg
  HA_PID=$!                  # record spawn pid
  echo $HA_PID > $PIDFILE    # record the PID to a file for `stop`.
  # !!! optional release of lock here...
  disown $HA_PID             # detach script from terminal.

服务不应该使用echo之类的; logger是更好的选择。除非hamonitor尝试读取某些内容,否则这可能不是您的问题。主要问题是start()如果你没有hamonitor将等待disown完成,所以 rc 脚本的开始永远不会完成。

通常,您可以查看 /etc/rc.d/init.d/functions ,提供指向您文件的链接,或提供您的发行版和版本(或至少 linux标准基础一致性,似乎定义了它应该如何在其不同版本中工作)。每个Linux上的文件可以不同。如果您了解脚本以查看预期的 environment 变量,文件等以及您在此文件中使用的功能,则可以自己查看此文件。例如,killproc最有可能在那里定义。