解决方案

解决方案

我创建了一个名为 init.d 脚本rmCluster它应该在关机时执行一个简单的 python 脚本,该脚本使用 boto 关闭位于的特定服务器集群,该集群具有 755 个权限,写法如下/etc/init.d/rmCluster

#!/bin/sh
#
# chkconfig: 0 1 1
# description: My service
#
# Author: Me
#
#
### BEGIN INIT INFO
# Provides: rmCluster
# Required-Start:
# Required-Stop:
# Default-Start:  0
# Default-Stop:  0
# Short-Description: My service
# Description: My service
### END INIT INFO

case $1 in
start)
python /usr/local/sbin/instanceStopper.py &
touch /tmp/theScriptWorks
;;
esac
exit 0

我还创建了一个/etc/rc0.d/S00rmCluster指向上述内容的符号链接。请注意,我正在成功触摸 /tmp 中的一个文件。

该python脚本的权限也是755,写法如下:

#!/usr/bin/env python

import boto.ec2
import subprocess

conn=boto.ec2.connect_to_region("us-west-2")
reservations = conn.get_all_instances()
cluster = []
inst_id = subprocess.Popen(["wget", "-q", "-O", "-", "http://169.254.169.254/latest/meta-data/instance-id"], stdout=subprocess.PIPE).communicate()[0]

for res in reservations:
    for inst in res.instances:
        if inst_id in inst.tags["Name"] and "cloudformation" not in inst.tags:
            cluster.append( "%s" %(inst.id) )

conn.terminate_instances(cluster)

请注意,python 脚本在直接调用时运行良好,在直接运行 init.d 脚本时也运行良好。我还尝试删除 python 脚本中的 shebang 并在 init.d 调用中指定 python 的路径,但仍然不起作用。

我最初的想法是,也许 python 库在此运行时不再可用,因此脚本失败,但我不确定如何检查。此外,我考虑过也许需要将其放置在 rc.x 目录中的其他位置。目前我已将其设置为 S00,它是唯一的 S00。Killall 我移至 S01,halt 我移至 S02;这些是 rc.0/ 中仅有的三个“S”脚本

我非常感谢你的帮助

解决方案

解决方案是结合@Jayan 和@Kjetil Joergensen 的回应。

init.d脚本的最终工作版本如下:

#!/bin/bash
#
# chkconfig: 2345 99 1
# description: My service
#
# Author: me
#
#
### BEGIN INIT INFO
# Provides: rmCluster
# Required-Start:
# Required-Stop:
# Default-Start:  0
# Default-Stop:  0
# Short-Description: My service
# Description: My service
### END INIT INFO


case "$1" in
start)
touch /var/lock/subsys/rmCluster
;;
stop)
/usr/bin/python /usr/local/sbin/instanceStopper.py
;;
esac
exit 0

主要变化如下:

  1. 将 'start)' 部分移至 'stop)' 部分
  2. 触摸“开始”部分的锁定文件
  3. 修改“chkconfig:”参数,使其与正常服务一起“启动”,并随它们一起被终止,从而阻止脚本尝试执行“网络”关闭后的操作,正如@Kjetil Joergensen 所注意到的

笔记:Python脚本没有改变。

有两个注意事项,一是它需要service start rmCluster在运行级别 0 和 6 期间运行才能关闭。对我来说这是可以接受的,因为它是在云配置期间设置的,因此将此步骤添加到 EC2 用户数据中很简单。第二是脚本在重新启动期间也会执行,这可能并不适用于每种用例。我必须做进一步调查,看看如何使只有运行级别 0 才能真正在此脚本上运行“停止”。

谢谢你们的帮助。

答案1

(几乎)您需要知道的一切都在 /etc/rc.d/rc 中,它是用于更改运行级别的 shell 脚本,它相当易读,因此应该很容易弄清楚它的作用。

其作用的简要描述如下:

  • 它首先检查每个 /etc/rc<runlevel>.d/K<num><subsystem> 脚本,通过查找 /var/lock/subsys/ 检查它是否已启动,如果已启动则运行停止
  • 然后,它检查每个 /etc/rc<runlevel>.d/S<num><subsystem> 脚本,通过检查 /var/lock/subsys/<subsystem> 来检查它是否已停止,然后在其上运行启动程序。

(可能有一些处理 /var/lock/subsys 的便利函数)

如果上述所有情况都是正确的,那么您可能需要做的是:

  • 确保存在 /var/lock/subsys/<yourscriptname>
  • 运行级别 0 似乎比较合适(除非您还想包含重新启动,即 6),并且您需要将其作为 /etc/rc0.d/K<num < 90><yourscriptname> 运行,网络在 90 时被终止,因此请将您的实现更改为停止而不是启动。您还可以将脚本作为相关运行级别的一部分“启动”(3、5、1 表示单用户无网络,2、4 表示未使用),只需在 /var/lock/subsys 中留下相应的内容即可
  • 您肯定希望摆脱 & 符号,因为您的 initscript 会在完成之前返回,这取决于它执行其余脚本的速度,它会达到 90 并终止网络,稍后某个时候它会杀死所有并最终停止。为了避免关机无限期挂起,您需要在脚本中执行适当的错误处理/超时处理,而不是仅仅启动它并将其余部分留给机会。

答案2

你为什么不尝试改变你的初始化脚本来开始

检查配置:2345 99 1

并将代码从“Start”案例移至“stop”,并有一个空的“start”案例,然后将脚本放入/etc/init.d 后执行 chkconfig --add。

注意:您可能必须删除已经创建的任何软链接。

另外,请确保在执行 init 脚本时加载了正确的“PATH”。由于您的 Python 程序已经是一个可执行文件,因此您可以像这样调用它

/路径/到/程序&

代替

python /路径/到/程序&

另外在 init 文件的“start”部分添加以下行:

触摸/var/lock/subsys/program

这基本上会创建一个锁定文件,当机器重新启动 | 停止时,系统将在启动停止之前检查每个服务的状态。如果系统发现服务未运行(如果锁定文件不存在),系统可能不会运行“停止”程序

相关内容