Melhorando o desempenho do script [closed]

1

Eu tenho trabalhado em um script que pode ser usado para reiniciar automaticamente meus serviços de monitoramento do Zabbix no caso de eles pararem de executar. Eu tenho o script funcionando muito bem, mas achei que poderia ser melhorado.

#!/bin/bash
zabbix_server="service zabbix-server"
zabbix_agent="service zabbix-agent"
logfile=zabbix_auto_restart.log
logfilePath=/etc/scripts/zabbix/$logfile
zabbix_server_running=0
zabbix_agent_running=0

grep_agent (){
    local retval=$(ps -ef | grep -v grep | grep zabbix_agentd | wc -l)
    echo $retval
}

grep_server (){
    local retval=$(ps -ef | grep -v grep | grep zabbix_server | wc -l)
    echo $retval
}

check_zabbix_agentd (){
    if (( $(grep_agent) == 0 ))
    then
       $zabbix_agent start
       echo 'date' "$zabbix_agent was stopped... Restarting" >> $logfile
       echo "************************************************" >> $logfile

       #Send email to notify that the script ran
       echo "$(date) $zabbix_agent was restarted from zabbix_restart.sh" | mutt -s "Zabbix Auto-restart Script Just Ran" <user email>

    else
       let zabbix_agent_running=1
    fi
}

check_zabbix_server (){
    if (( $(grep_server) == 0 ))
    then
       $zabbix_server start
       echo 'date' "$zabbix_server was stopped... Restarting" >> $logfile
       echo "************************************************" >> $logfile

       #Send email to notify that the script ran
       echo "$(date) $zabbix_server was restarted from zabbix_restart.sh" | mutt -s "Zabbix Auto-restart Script Just Ran" <user email>

    else
       let zabbix_server_running=1
    fi
}

main_loop (){
    until ((zabbix_server_running == 1 && zabbix_agent_running == 1));
    do
        check_zabbix_agentd
        check_zabbix_server
        sleep 1.5
    done
}

main_loop
    
por Evan Bechtol 19.06.2015 / 01:52

1 resposta

4

O que você está realmente fazendo errado é duplicar seu esforço - basicamente, todas as ocorrências codificadas de _agent ou _server parecem ser completamente redundantes.

Por exemplo, se estiver sendo executado em um sistema linux, você pode descartar completamente as funções grep_...() e consolidar as duas check_... s em uma única entidade que funcione como:

email(){ 
    mutt -s "Zabbix Auto-restart Script Just Ran" \<user email\>
}
prlog(){ 
    date +"%x %X:%tservice $1${2+%n************************}"
}
chk_run()
    while  [ "$#" -gt 0 ]
    do     if     ps -C zabbix_"$1"
           then   : "$(($1=1))"
           else   set zabbix_"$@"
                  service "$1" start || eval >&2 '
                  prlog   "$1 restart failed."  +; exit '"$?"
                  prlog   "$1 restarted."       +  >&2
                  prlog   "$1 restarted from $0." |email
           fi;    shift
    done

A chave para isso é que você só chamaria chk_run com uma lista de argumentos, cada membro do qual indicaria o que deveria estar verificando cada iteração.

loop()
    until [ "$(($1&&$2))" -eq 1 ]
    do    chk_run "$@"
          sleep 2
    done  >/dev/null 2>>"$log"
agentd=0 server=0 loop agentd server

POSIXly, a única coisa que deve ser alterada é o comando ps - porque POSIX não especifica a opção -C . E assim você poderia apenas alterar a linha if para se parecer com:

if    ps -eocomm= |
      grep -xqF zabbix_"$1"

Além de mutt , service e ps otimização, tudo deve ser uma linguagem de comando padrão.

Pelo menos uma vantagem da sintaxe padrão é que o #!/bin/bash hash-bang é completamente desnecessário - não há âncora aqui para alguma extensão específica do shell e, portanto, deve funcionar exatamente da mesma maneira em todos os shells que buscam Conformidade com POSIX. Isso significa que #!/bin/dash é uma otimização muito simples (e provavelmente eficaz) nesse caso.

Claro, otimizado ou não, esse script quase sempre será sleep .

Recusei-me a definir $log - principalmente porque não havia nada a dizer sobre o modo como você o definiu - tudo bem - mas você pode querer deixar de defini-lo. Se você puder ter certeza do ambiente de chamada do script, ele poderá criar um meio muito simples de passar parâmetros. O que quero dizer é que, se o script é chamado ./script e já foi feito executável, então ...

log=/dev/tty ./script

... definirá o valor para $log no ambiente de ./script quando for chamado.

Eu uso /dev/tty como um arquivo de exemplo porque acho que você deve começar com isso enquanto ajusta a sua satisfação. Se os blocos de código aqui forem colocados em ./script e forem lançados como descrito acima, eles serão gravados em tempo real no seu terminal, em vez de em algum arquivo de saída - e assim você poderá ter uma ideia bem clara sobre o que acabará em seu logfile real quando você eventualmente o chama como:

log=./real/logfile ./script

Como alternativa, como algo como um comportamento híbrido, você pode alterar o script de modo que diga " 2>>"$log" ":

2>>"${log:-/hardcoded/default/path/to/logfile}"

... nesse caso, o shell usará apenas o valor codificado para $log , se ainda não estiver definido. Isso significa que qualquer um de:

export log=/dev/tty; ./script
log=/dev/tty ./script

... ainda vai escrever o arquivo de log no terminal, e qualquer um dos ...

log= ./script
unset log; ./script

... gravará no caminho codificado e ...

./script

... grava no caminho codificado ou em algum outro local, dependendo se já existe um valor não nulo para $log exportado para o ambiente atual do shell.

    
por 19.06.2015 / 02:57