A parte do Script Python falhou ao executar dentro do init.d / no RedHat 6.5, por quê?

2

Eu criei um script init.d chamado rmCluster que deve executar um script python simples no desligamento que usa o boto para desligar um determinado cluster de servidores, com 755 perms, localizado em /etc/init.d/rmCluster escrito como:

#!/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

Também criei um link simbólico em /etc/rc0.d/S00rmCluster , que aponta para o acima. Observe que estou tocando um arquivo em / tmp que está ocorrendo com sucesso.

O script python também tem 755 permissões e está escrito como:

#!/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)

Note que o script python funciona perfeitamente quando chamado diretamente e também funciona bem quando executar o script init.d diretamente. Eu também tentei remover o shebang no script python e especificando o caminho para o python dentro do init.d call e ele ainda não funciona.

Minha inicial é que talvez as bibliotecas python não estejam mais disponíveis durante esse tempo de execução, então o script falha, mas não tenho certeza de como verificar isso. Além disso, eu contemplei que talvez ele precise ser colocado em algum outro lugar nos diretórios rc.x. Atualmente eu tenho definido em S00 e é o único S00. Killall eu mudei para S01 e parei de me mudar para S02; estes são os únicos três scripts "S" dentro do rc.0 /

Eu gostei da ajuda

Solução

A solução foi uma combinação de entrada da resposta de @Jayan e @Kjetil Joergensen.

A versão final de trabalho do script init.d é a seguinte:

#!/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

As principais mudanças foram:

  1. Mover a parte "start" em uma parte "stop"
  2. Tocando no arquivo de bloqueio na parte "início"
  3. Modificando o parâmetro 'chkconfig:' para que ele 'inicie' com os serviços normais e seja morto com eles também, evitando assim que o script tente executar o desligamento após 'rede', como notado por @Kjetil Joergensen

Nota: o script python não foi alterado.

Duas ressalvas, uma é que é necessário executar service start rmCluster para que seja encerrado durante o nível de execução 0 e 6. Para mim, isso foi aceitável, pois está sendo configurado durante o provisionamento de formação de nuvens, portanto é trivial adicionar esse passo nos dados do usuário do EC2. A segunda é que o script é executado durante as reinicializações, o que pode não ser ideal para cada caso de uso. Vou ter que fazer uma investigação mais aprofundada para ver como fazer com que apenas o nível de execução 0 realmente execute 'stop' neste script.

Obrigado a ambos pela ajuda.

    
por DefionsCode 09.10.2014 / 21:46

2 respostas

1

(Quase) Tudo o que você precisa saber está em /etc/rc.d/rc é o shell-script usado para mudar os runlevels, é razoavelmente legível na medida em que deve ser um pouco fácil descobrir o que ele faz. / p>

A breve descrição do que faz é:

  • Primeiro, ele passa por todos os /etc/rc<runlevel>.d/K<num><subsystem> script, verifica se é iniciado procurando por / var / lock / subsys / e executa a parada se for
  • Em seguida, ele passa por todos os /etc/rc<runlevel>.d/S<num><subsystem> script, verifica se ele está parado, verificando se há / var / lock / subsys / < subsystem > e começa a correr.

(Há provavelmente alguma função de conveniência ao lidar com / var / lock / subsys)

Se tudo antes disso for verdade, provavelmente você vai querer:

  • Verifique se há um / var / lock / subsys / < seu nome > presente
  • O nível de execução 0 parece apropriado (a menos que você também queira incluir a reinicialização, que é 6), e você desejará executá-lo como /etc/rc0.d/K<num < 90 > < nome do seu autor & gt ;, a rede é eliminada aos 90, por isso, altere a implementação para parar em vez de iniciar. Você poderia potencialmente "iniciar" seu script como parte dos runlevels relevantes (3,5, sendo 1 usuário único sem rede e 2,4 não sendo usado) deixando apenas o material apropriado em / var / lock / subsys
  • Você definitivamente quer se livrar do "e" comercial, pois seu initscript retornará antes de ser feito, dependendo de quão rápido ele mastigue o resto dos scripts, ele chegará a 90 e matará a rede, em algum momento mais tarde vai chegar ao killall e eventualmente parar. Para evitar o desligamento interrompido indefinidamente, você vai querer fazer o tratamento adequado de erros / timeout no seu script, em vez de apenas desligá-lo e deixar o resto ao acaso.
por 10.10.2014 / 01:22
0

Por que você não tenta alterar seu script de inicialização para começar com

chkconfig: 2345 99 1

E mova seu código do caso "Start" para "stop" e tenha um caso "start" vazio E então, chkconfig --add depois de colocar seu script em /etc/init.d

Observação: você pode ter que excluir quaisquer softlinks que você já tenha criado.

Além disso, certifique-se de ter o "PATH" adequado carregado quando o script de inicialização for executado. Já que seu programa em Python já é um arquivo executável, pode ser que você simplesmente chame como

/ path / to / program &

em vez de

python / path / to / program &

Também na seção "start" do arquivo init, adicione a seguinte linha:

toque em / var / lock / subsys / programme

Que basicamente cria um arquivo de bloqueio e quando a máquina está reinicializando | Ao parar, o sistema verificará o estado de cada serviço antes de iniciar uma parada. Se o sistema achar que um serviço não está em execução (se o arquivo de bloqueio não estiver presente) o sistema pode não executar o procedimento "stop"

    
por 10.10.2014 / 00:30