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.

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.


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.


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

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.