Pure bashconstruído em, sem coreutils
Descobri que esta solução funciona em bashdepender de um built-in comando sem chamar um executável externo. Funciona em sistemas onde, eventualmente, nem sequer são instalados os coreutils [ 1 ]
YourCommand & read -t 300 ; kill $! # 1st version
YourCommand & read -t 300 || kill $! # 2nd version
Explicações : como de costume quando você enviar um comando no fundo com &, seu PID é armazenado na variável interna $!(presente na versão moderna dash, csh, bash, tcsh, zsh...).
O que realmente faz a diferença entre as conchas é a presença do built-in comando read[ 2 ] e da opção -t. Na 1ª versão, se o usuário não concluir uma linha de entrada antes da quantidade especificada de segundos, a instrução será encerrada e um código de retorno de erro será gerado.
-t TIMEOUT Faz com que a leitura atinja o tempo limite e retorne a falha se uma linha completa de entrada não for lida dentro de segundos de TIMEOUT.
A segunda versão funciona como a 1ª, mas você pode abortar o tempo limite final pressionando enter.
De fato, o operador ou ||executa a killinstrução somente se o readcomando sair com um código de retorno diferente de zero, como quando o tempo limite expirar. Se você pressionar enterantes desse momento, ele retornará 0 e não matará seu comando anterior.
Soluções Coreutils [ 1 ]
Quando coreutils estão presentes em seu sistema e você não tem nenhuma necessidade de economizar o tempo e os recursos para chamar um programa externo, timeoute sleepe são ambos excelentes maneiras para alcançar seu objetivo.
timeoutO uso de timeouté direto.
Eventualmente, você pode considerar usar também a -kopção de enviar um sinal de interrupção adicional se o primeiro falhar.
timeout 5m YourCommand # 3rd version
sleep
Com sleepvocê, você pode usar sua fantasia ou inspirar-se [ 3 ] . Observe que você pode deixar seu comando em segundo plano ou em primeiro plano (por exemplo, topgeralmente precisa estar em primeiro plano).
YourCommand & sleep 5m; kill $! # 4th Background
YourCommand & pid=$! ; (sleep 5m; kill $pid;) & # 5th Background
bash -c '(sleep 5m; kill $$) & exec YourCommand' # 6th Foreground
(cmdpid=$BASHPID; (sleep 5m; kill $cmdpid) & exec YourCommand) # 7th Foreground
Explicações
- Na quarta versão, você executa em segundo plano
YourCommande, em seguida, seu shell sleepfica por 5 minuites. Quando terminar, o último processo em segundo plano ( $!) será eliminado. Você para sua concha.
-
Na quinta versão, você executa em segundo plano
YourCommande armazena imediatamente esse PID na variável $pid. Em seguida, você executa em segundo plano uma soneca de 5 minutos e seu consequente comando que mata o PID armazenado. Como você enviou esse grupo de comandos em segundo plano, não interrompe seu shell. Você precisa armazenar o PID em uma variável porque o valor de $!pode ser atualizado por uma eventual execução de outro programa em segundo plano. Em palavras simples, você evita o risco de matar o processo errado ou nenhum processo.
- Na 6ª versão, ele é chamado de novo shell bash que se suicida em 5 minutos
$$, e então é executado seu comando que permanece em primeiro plano.
- Na 7ª versão, é invocado um subshell
()que armazena seu PID em uma variável ( cmdpid) e se mata com outro subshell enviado na execução em segundo plano, depois executa YourCommand em primeiro plano.
É claro que em cada versão você pode enviar o sinal de interrupção necessário, do padrão ao extremo kill -9 , para ser usado apenas quando realmente necessário.
Referências
- [ 1 ] Os Coreutils
- [ 2 ] Guia para iniciantes do Bash
- [ 3 ] O BashFAQ