bash reinicia mysql quando correu bem na parte SSH, mas não no cronjob

3

Meu sistema é centos 6.5,

Eu escrevo um simples bash shell para checar se o mysql está travado, reinicie o serviço novamente. Eu coloco em /home/myspace/mysql.sh chown root:root /home/myspace/mysql.sh e então corro cada minuto por crontab.

#!/bin/bash
mysql --host="localhost" --user="root" --password="password" --database="test" --execute="select id from test limit 1"
if [ $? -eq 0 ]; then echo "";
else
 /usr/bin/sudo service mysql stop
 pkill mysql
 /usr/bin/sudo service mysql start
 echo "error $(date)" >> /home/myspace/restart_log.txt
fi

Agora tenho duas perguntas.

  1. Por que no meu código, if ... else ... não está funcionando? Quero dizer, o servidor mysql não tem nenhum problema, ele pode executar "select id from test limit 1" e obter resultado, mas o script ainda executa o código em else case.

  2. em /var/log/sucure , mostra root : sorry, you must have a tty to run sudo ; TTY=unknown ; PWD=/root ; USER=root ; COMMAND=/sbin/service mysql stop . %código%. E o servidor mysql está inativo.

UPDATE: Agora eu tentei o código @Anthon dado:

#!/bin/bash
RESULT='mysql --host="localhost" --user="root" --password="password" --database="test" --execute="select browser from test limit 1"'
if [ $? -eq 0 ]; then 
   echo "mysql select ok"
else
  /usr/bin/echo "mysql select failed"
  sudo service mysql stop
  pkill mysql
  /usr/bin/sudo service mysql start
  echo "error $(date)" >> /home/myspace/restart_log.txt
fi

funciona bem em root : sorry, you must have a tty to run sudo ; TTY=unknown ; PWD=/root ; USER=root ; COMMAND=/sbin/service mysql start part (retornar mysql select ok)

mas não funciona em SSH (cada minuto escreve erro em cronjob e o servidor mysql nunca inicia)

Este problema é causado por /home/myspace/restart_log.txt ? OU PATH ? Como resolver isso? obrigado.

solve Obrigado por todos, finalmente eu resolvi isso. @ Método de Sigi talvez bom, mas não está funcionando na minha situação. @ Resposta da Anthon escrever melhor do que eu, mas ainda não está funcionando. @Emmanuel, dada a resposta é mais próxima que a dos outros. Após um longo teste, compartilhei o código final de trabalho para todos.

#!/bin/bash
PATH=/bin:/usr/bin:/sbin:/usr/local/bin
# cronjob need clear where is the path
# mysql under path /usr/local/bin
mysql --host="localhost" --user="root" --password="password" --database="test" --execute="select id from test limit 1"
if [ $? -eq 0 ]; then echo "";
# mysql run well nothing to do, make a
else
 sudo /etc/init.d/mysql stop
 pkill /usr/local/bin/mysql
# It should be pkill /usr/local/bin/mysql, not pkill mysql, wrong write will cause below code not working
 sudo /etc/init.d/mysql start
 sudo /etc/init.d/httpd restart
# Some strange behave, after mysql restart, apache will die, so should add httpd restart 
 echo "error $(date)" >> /home/myspace/restart_log.txt
fi
    
por cj333 24.04.2014 / 10:28

5 respostas

1

Forçar o PATH no seu script, cron não pode fornecer o mesmo caminho que o que você tem em uma sessão de terminal.

EDIT:
Em um terminal, pegue seu PATH:

env | grep "^PATH="   
PATH=/sbin:/usr/sbin:/usr/local/sbin:...   (you will have different value

Recorte e cole essa linha no seu script abaixo do #!/bin/bash

#!/bin/bash

PATH=/sbin:/usr/sbin:/usr/local/sbin:     (put your path 
export PATH

(isso é apenas por exemplo)

Pode haver outra variável para adicionar no seu script; procure a variável cujos nomes contenham a string 'MYSQL' com env | grep MYSQL e set | grep MYSQL

    
por 29.04.2014 / 20:17
4

O que você quer fazer é verificar se o processo do servidor de banco de dados ainda está ativo. O MySQL fornece um comando para isso: mysqladmin ping

Sugiro que você coloque o seguinte no seu crontab do sistema (edite o arquivo /etc/crontab ):

* * * * *  root  /usr/bin/mysqladmin --host="localhost" --user="root" --password="password" ping || /usr/sbin/service mysql restart

Isso fará o ping do banco de dados a cada minuto e emitirá um "reinício" se ele não responder.

Não é necessário consultar uma tabela arbitrária e testar o resultado para determinar se o banco de dados está ativo.

Veja o que a documentação oficial precisa diga sobre o subcomando ping :

ping
Check whether the server is available. The return status from mysqladmin is 0 if the server is running, 1 if it is not. This is 0 even in case of an error such as Access denied, because this means that the server is running but refused the connection, which is different from the server not running.

Melhor ainda seria usar um watcher de processo dedicado (como monit , upstart ou systemd ) para manter o mysql processo vivo.

    
por 26.04.2014 / 20:40
3

Como seu log indica (ponto 2), a parte else está sendo executada, mas apenas sai na primeira instrução.

Se quiser depurar algo que você suspeita que não esteja sendo executado, certifique-se de fazer um eco no início de ambos os caminhos (você sempre poderá removê-los quando as coisas funcionarem). Seu eco vazio na parte if não é útil, seria imprimir algo, você teria notado que isso não é impresso, mas melhor seria ter um echo "takeing else route" na linha após o else .

Para que sudo funcione, você provavelmente terá que editar o arquivo /etc/sudoers e comentar requiredtty (da página man):

requiretty      If set, sudo will only run when the user is logged in
                to a real tty.  When this flag is set, sudo can only be
                run from a login session and not via other means such
                as cron(8) or cgi-bin scripts.  This flag is off by
                default.

Para obter feedback, seu script deve ficar parecido com:

#!/bin/bash
mysql --host="localhost" --user="root" --password="password" --database="test" --execute="select id from test limit 1"
if [ $? -eq 0 ]; then 
   echo "mysql select ok"
else
   echo "mysql select failed"
 /usr/bin/sudo service mysql stop
 pkill mysql
 /usr/bin/sudo service mysql start
 echo "error $(date)" >> /home/myspace/restart_log.txt
fi
    
por 24.04.2014 / 10:40
2

Fora do tópico: Você realmente quer reiniciar o serviço a cada minuto? Quando os serviços falham devido a alguma outra falha, tentar reiniciar a cada minuto é terrível. (Nunca elimine o banco de dados de teste ...) (Você pode criar um script mais inteligente que verifique o último tempo de falha e espere pelo menos 1 hora antes de tentar novamente e enviar uma correspondência para um operador)
No tópico: Quando você não pode depender do returnvalue do mysql, você pode tentar selecionar alguma string:

FLAG="$(mysql --host="localhost" --user="root" --password="password" --database="test" \
   --execute="select count(*) as MYSPECIALFLAG from test")"
if [[ ${FLAG} != *MYSPECIALFLAG* ]]; then
   my_restart_function
fi

Outra questão: sudo sem terminal: Reiniciar o serviço é de responsabilidade do root. O administrador do sistema executando root gostaria de verificar seu próprio crontab quando algo está reiniciando o serviço a cada minuto. Portanto, convença o administrador do sistema de que ele deseja executar seu script de mágica como root, e você não tem problemas com o sudo.

    
por 24.04.2014 / 13:04
0

MAIS PROVÁVEL - você precisa especificar o serviço correto, no CENTOS 6.5 seria

service mysqld stop

não

service mysql stop

Isso também seria o motivo pelo qual o pkill não está funcionando, você precisaria de pkill mysqld

Mas o comando real a usar é service mysqld restart e evita o uso completo do pkill.

Outras notas gerais ao executar no cron:

1) No CentOS 6.5, o caminho para o eco é / bin / echo

2) Se você executar o cron como root, não execute os comandos através do sudo (isso evitará tty / pty, ambiente e problemas de permissão que o sudo pode introduzir)

3) Especifique o caminho completo para pkill = / usr / bin / pkill no CentOS 6.5

4) Especifique o caminho para o mysql = / usr / bin / mysql no CentOS 6.5

Como Emmanuel alude, provavelmente não há caminhos suficientes definidos na variável PATH quando executado através do cron. Geralmente, forneça o caminho completo para todos os comandos.

    
por 01.05.2014 / 01:22