Existe uma maneira de chamar um comando com um limite de tempo definido e matá-lo quando esse tempo passar? [duplicado]

10

Eu estava trabalhando em um script de construção de integração contínua quando surgiu a necessidade de tal comando. Basicamente, eu preciso lançar um comando com um limite de tempo para que ele seja executado antes de ser morto e todos os comandos devem ser executados imediatamente assim que este comando iniciar o processo de tempo limitado em segundo plano e não esperar que ele chegue ser morto. Uma espécie de concorrência assíncrona.

Veja o que eu imagino:

timelimited --limit=10 'somecommand --someoptions'
someothercommand //This gets launched immediately once 'timelimited' is done creating the background process
    
por carlossless 12.12.2012 / 15:49

3 respostas

8

Entrada de FAQ BASH # 68: "Como faço para executar um comando e abortar (timeout) após N segundos?" / a>

FIRST check whether the command you're running can be told to timeout directly. The methods described here are "hacky" workarounds to force a command to terminate after a certain time has elapsed. Configuring your command properly is always preferable to the alternatives below.

If the command has no native support for stopping after a specified time, then the best alternatives are some external commands called timeout and doalarm. Some Linux distributions offer the tct version of timeout as a package. There is also a GNU version of timeout, included in recent coreutils releases.

    
por 12.12.2012 / 15:54
10

Se timeout e doalarm não estiverem disponíveis (por exemplo, OS X), você poderá usar expect :

timeout() {

    time=$1

    # start the command in a subshell to avoid problem with pipes
    # (spawn accepts one command)
    command="/bin/sh -c \"$2\""

    expect -c "set echo \"-noecho\"; set timeout $time; spawn -noecho $command; expect timeout { exit 1 } eof { exit 0 }"    

    if [ $? = 1 ] ; then
        echo "Timeout after ${time} seconds"
    fi

}
    
por 12.12.2012 / 16:28
2

Outra possibilidade é fazer isso manualmente. No entanto, só faria isso se as opções que Ignacio sugere em sua resposta não estiverem disponíveis:

timeout_f () {
    $1 &
    sleep $2
    kill $! # ends somecommand if still running
}

timeout_f 'somecommand --someoptions' 10 && #need 2 &'s
echo "forked.." # happens immediately
    
por 12.12.2012 / 16:12