find -exec exit 1 \; Não funciona nem encontra -exec sh -c exit 1 \;

3

Usando o Enterprise Linux 5/6, Bash 4.x Eu quero esse tipo de lógica:

# IF temp file exists, exit because we are restarting already     
find /tmp/restarting_server -mmin -10 -exec exit 1

lsof -i TCP:1234 || declare Server_is_down=TRUE
    if ! [ -z $Server_is_down ]; then restart_server
    fi
# Restart Server Function
restart_server() {
    touch /tmp/restarting_server 
    service server restart
    rm -f /tmp/restarting_server 
}

O problema é que o find -exec não gosta de builtins, parece. Eu sei que posso fazer uma instrução if, em seguida, para verificar o arquivo e sair lá, mas eu quero saber como fazer isso em um find -exec (ou eu iria resolver por uma boa solução xargs).

    
por Gregg Leventhal 13.03.2014 / 17:15

4 respostas

3
while [ -f /tmp/restarting_server ] ; do {
    [ $((i=i+1)) -ge 10 ] && exit 1
    sleep 1 
} ; done

Você não precisa de find se já sabe o nome do arquivo, o nome do caminho exato e as condições sob as quais um arquivo deve ser aceito de forma aceitável.

Assim, o outro problema - sair do seu script da sua declaração -exec - talvez não seja o problema que você considera ser. find não cria uma opção para kill ing seu shell pai porque o shell já o fornece.

find … -exec sh -c kill\ $$ \;

Considere também que você pode usar essa construção para sinalização com base em caminhos existentes, mesmo que não tenha certeza de onde eles estarão:

trap 'stuff to do' USR1    
… #later… 
find … -exec sh -c kill\ -USR1\ $$ \;

E isso também abre muitas outras opções para você:

find … -exec sh -c exec… 

EDITAR:

Acabei de pensar em outras opções que envolvem parameter expansion para fazer com que seu shell saia sem find ' -exec ', o que poderia ser usado de outras maneiras:

hold_file="$(find . -name file)"
${hold_file:+false} : || exit 1

ou

N= ; hold_file="$(find . -name file)"
${hold_file:+${N:?lock file remains, exiting...}}

Os dois só causarão uma saída se a variável à qual você atribui find stdout não for null ou não definida. E, claro, caso deseje falhar com base em um achado vazio, você pode fazer o mesmo com :- em vez de :+ e omitir totalmente a variável de valor $N ull.

Ou apenas para alterar o status de saída de find :

$(find . -name file -exec echo false \; ) : || exit 1
    
por 13.03.2014 / 17:46
4

Você pode verificar se ele retornou um resultado:

[ -z "$(find /tmp/restarting_server -prune -mmin -10)" ] || exit 1
    
por 13.03.2014 / 17:23
1

Você pode simplesmente fazer isso:

if [ "$(find /tmp -maxdepth 1 -mindepth 1 -name restarting_server -mmin -10)" = '/tmp/restarting_server' ]
then
    exit 1
fi

Isso funciona mesmo se você estiver usando set -o errexit (o que você deve).

    
por 13.03.2014 / 17:23
1

find é um programa próprio. O argumento para -exec é outro comando. Quando um comando como find … -exec foo {} \; é executado, o shell tem find como um subprocesso e cada instância de foo é um subprocesso de find . O comando exit existe apenas como um shell embutido, não como um comando independente; um programa exit seria impossível, já que teria que fazer com que o processo pai fosse encerrado.

A solução para seu problema imediato é fazer com que find informe se encontrou ou não um arquivo, e faça o shell sair se houver uma correspondência. Você não pode usar o status de retorno de find , porque considera a ausência de qualquer correspondência como um motivo de sucesso. Em vez disso, teste a saída.

if [ -n "$(find /tmp/restarting_server -mmin -10)" ]; then exit; fi

Aqui, o arquivo deve ser um arquivo regular, se existir. No entanto, em geral, o arquivo poderia ser um diretório, caso em que find iria atravessá-lo. Então, diga find para parar quando encontrar uma correspondência.

if [ -n "$(find /tmp/restarting_server -mmin -10 -prune)" ]; then exit; fi

No entanto, o script resultante não é confiável. Você não está implementando um bloqueio corretamente. Se duas instâncias do script começarem quase ao mesmo tempo, é possível ter, por exemplo:

  1. O script 1 é iniciado, não vê nenhum arquivo restarting_server e prossegue alegremente.
  2. O script 2 é iniciado, não vê nenhum arquivo restarting_server e continua alegremente.
  3. O script 1 vê que o servidor está inativo e decide reiniciá-lo.
  4. O script 2 vê que o servidor está inativo e decide reiniciá-lo.
  5. O script 1 cria /tmp/restarting_server .
  6. O script 2 atualiza o registro de data e hora em /tmp/restarting_server .
  7. O script 1 chama service server restart .
  8. O script 2 chama service server restart .
  9. O script 1 remove /tmp/restarting_server .
  10. O script 2 chama rm -f /tmp/restarting_server , o que não faz nada.

Ligue para flock para implementar o bloqueio adequado.

(
  lsof -i TCP:1234 >/dev/null ||
  service server restart
) 3>/var/lock/maybe_restarting_server

Você não precisa de um tempo limite para invalidar o bloqueio nas reinicializações, pois o bloqueio é mantido na memória.

    
por 14.03.2014 / 02:16

Tags