我有 2 个运行 HAProxy 的 Amazon Linux EC2 实例。我想从另一个实例监控每个实例,如果一个实例不可用,另一个实例将发出 API 命令将弹性 IP 移动到活动服务器。
我创建了一个 Bash 脚本来每 XX 秒进行一次监控。我需要将脚本设置为作为服务运行,因此我创建了一个服务包装器,并根据我找到并注册为服务的模板放置在/etc/init.d 中。
问题是当我 #service hamonitor 启动发出命令时,它说"正在启动 hamonitor...",但我从未看到 OK 消息,如果我发出停止命令,它会失败,如果我发出状态命令,它说它没有运行。但是,如果我检查日志,它会显示脚本实际上正在运行。我假设我需要一个适当的 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
一些 Linux 发行版有upstart和其他init;我假设你有init
. 该chkconfig
用于维护符号链接。 您应该确认评论,
# 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
将信息发送到系统日志;我想应用程序脚本是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
试图从某些东西中读取。 主要是问题是,如果你不disown
,start()
会等待hamonitor
完成,所以rc脚本的开始永远不会完成。
一般来说,您可以查看/etc/rc.d/init.d/functions,提供指向您的文件的链接,或提供您的发行版和版本(或者至少是Linux 标准基本一致性,这似乎定义了它应该如何在其不同版本中工作)。 该文件在每个 Linux 上都可以不同。 如果您了解脚本编写,则可以自己查看此文件,以了解需要哪些环境变量、文件等以及在此文件中使用哪些函数。 例如,killproc
很可能在那里定义。