Como restringir o tempo de execução de um programa no Linux?

10

Eu tenho várias simulações para fazer, cada uma é invocada python simulate.py <parameter list>. O problema com essas simulações é que algumas delas ficam paralisadas sem sair, o que me impede de executá-las em lote com um script simples.

O que eu precisaria é de alguma forma de comando "restrição de tempo de execução" que mataria automaticamente o processo (de preferência pressionando virtualmente Ctrl + C , mas acho que o simples assassinato também servirá) depois de um tempo especificado, se o processo não terminou graciosamente por si só.

É claro que eu mesmo posso escrever esse script, mas desconfio que alguém já o tenha feito antes de mim, para que não precise reinventar a roda gastando horas com ps, timee bash manuais.

Adam Ryczkowski
fonte

Respostas:

15

Solução potencial nº 1

Use o timeoutcomando:

$ date
Mon May  6 07:35:07 EDT 2013
$ timeout 5 sleep 100
$ date
Mon May  6 07:35:14 EDT 2013

Você também pode colocar um guarda no timeoutcomando para killo processo se ele não parar depois de um certo período de tempo.

$ date
Mon May  6 07:40:40 EDT 2013
$ timeout -k 20 5 sleep 100
$ date
Mon May  6 07:40:48 EDT 2013

Isso aguardará até 20 segundos depois que o processo sleep 100deveria ter parado, se ainda estiver em execução, timeoutenviará um killsinal.

Solução potencial # 2

Uma maneira alternativa, embora o método mais arriscado seja o seguinte:

./myProgram &
sleep 1
kill $! 2>/dev/null && echo "myProgram didn't finish"

Encontrei esta técnica no Stack Overflow em uma pergunta intitulada: Limitando o tempo de execução de um programa no Linux . Especificamente esta resposta .

OBSERVAÇÃO: por um comentário deixado por @mattdm, o método acima pode ser arriscado, considerando que não houve novos processos iniciados desde o seu processo. Portanto, nenhum novo PID foi atribuído. Diante disso, essa abordagem provavelmente não deve ser usada, mas é aqui apenas como referência para uma abordagem geral do problema. O timeoutmétodo é a melhor opção dos 2.

slm
fonte
Mas será garantido que o script sempre levará todo esse tempo. No meu caso, não são 1 segundo, mas 15 minutos.
Adam Ryczkowski
Mas a outra solução encontrada nessa pergunta deve ser exatamente o que eu preciso. Obrigado!
Adam Ryczkowski
2
Suponha que a myProgram conclusão seja concluída em menos tempo do que sleep(uma suposição não razoável, pois o objetivo é definir um tempo de execução máximo permitido). Em seguida, você envia um sinal para um PID inexistente (nenhum dano real causado) ou para qualquer processo aleatório no sistema (potencialmente fatal).
um CVn
1
@ MichaelKjörling, obrigado pelo feedback. Atualizei minha resposta com o mesmo comentário que o OP deixou também. Parece que o timeoutcomando faz exatamente o que ele está procurando, esperando o OP responder aos meus comentários.
Slm
@ SLI timeoutdeve ser a solução que eu preciso. Estou testando no momento
Adam Ryczkowski 6/13
4

Eu encontrei algo um pouco melhor, do que timeout: timelimit.

Tem várias vantagens; Uma é que o usuário pode interromper manualmente a execução pressionando "Ctrl + C".

O timelimitprograma está disponível no repositório Debian.

Adam Ryczkowski
fonte
1
Tentando entender as diferenças entre o limite de tempo e o tempo limite. o tempo limite pode ser parado com um Ctrl + C. Quais são as outras vantagens?
Slm
Bem, meu tempo limite não pode. Eu uso o Mint 14 (baseado no Ubuntu Quantal).
Adam Ryczkowski
3

Você pode ajustar o tempo da CPU e outras coisas ulimit, especialmente para o tempo da CPU:

$ ulimit -t 60      # limit to 60 seconds
$ program
RSFalcon7
fonte
Consulte estas perguntas e respostas de perguntas e respostas: unix.stackexchange.com/a/4666/7453 . O @Gilles fornece uma boa visão geral do uso do ulimit para esse fim.
Slm
0

O Bash usa uma variável chamada $BASHPIDela pode ser usada em uma situação como, por exemplo:

#!/bin/bash
do_face() {
    local parent=$1
    echo $BASHPID > pid
    sleep 10
    echo "Killing parent $parent"
    kill $parent
}

ME=$BASHPID
eval $(echo "do_face $ME &")
sleep 20 && kill $(cat pid) && echo "killed child $(cat pid)"
exit 1

Você pode alterar o argumento na chamada para sleepem do_face()que 100, em vez de 10ver o que acontece quando a criança leva muito tempo para fazer suas tarefas. Apenas mude a chamada para adormecer do_face()para uma chamada para o seu executável e, se levar muito tempo, o script irá eliminá-lo, 20segundos é o valor limitador neste exemplo. Os parâmetros podem ser implementados para que isso se torne um script simples de chamar e possa ser chamado por outro script em lote ou o que for. Manipular os arquivos pid para cada processo simultâneo é um problema que precisará ser tratado, talvez use sub-diretórios diferentes ...

NB: No GNU Linux, é sleeppossível usar argumentos de ponto flutuante, como sleep 0.1dormir por um décimo de segundo.

Overloaded_Operator
fonte