Em alguns sistemas, certos comandos como df
e prtdiag
(somente Sun) podem travar indefinidamente devido a várias causas. Estou tentando fortalecer meus ksh
scripts para que, caso eles se deparem com eles, eles falhem em vez de paralisarem indefinidamente. Para esse fim, estou planejando usar o timeout
comando, mas ele não está universalmente disponível em 100% de nossa área ocupada, então devo usar condicionalmente timeout
apenas se existir e o comando simples, se não existir. Eu gostaria de encontrar uma linha compacta para isso, pois precisarei conectá-la a várias cadeias de comando existentes com aumento mínimo de complexidade.
Para a maioria dos comandos, isso é simples. Mas timeout
retorna um código de status diferente de zero quando atinge o tempo limite (124, 143 ou 271), e não apenas quando falha na execução porque não existe (1 ou 127). Portanto, o operador simples ||
não pode diferenciar entre "nenhum comando" e "a operação expirou". Como resultado, isso não funcionará:
(timeout 5 df || df) # will execute bare df if there is no timeout *or* if the first df times out, thus hanging
Outra opção que testa o comando timeout sem tentar executá-lo também não funciona pelo mesmo motivo. O tempo limite em si em uma condição de tempo limite terá ||
a mesma aparência que se o comando timeout não existisse:
(command -v timeout >/dev/null && timeout 5 df || df) # same result
Eu preciso de um if-then-else compacto para códigos de retorno em que o código de retorno da última parte ( else ) seja conduzido apenas pela primeira parte ( if ) e não seja influenciado pelo do meio ( then ). Se o timeout
comando existir, use-o; caso contrário, execute o comando simples. Não quero que uma condição de tempo limite resulte na execução do comando simples.
Aqui está uma maneira que funciona corretamente, testando duas vezes:
(command -v timeout >/dev/null || df; command -v timeout >/dev/null && timeout 5 df)
Mas isso não parece muito elegante; Estou tendo que repetir command -v timeout >/dev/null
duas vezes. Outra opção que funciona com apenas um teste:
(command -v timeout >/dev/null; if [ $? -eq 0 ]; then timeout 5 df; else df; fi)
Mas o if-then-else-fi explícito com ponto e vírgula e coisas assim parece pesado e não tão compacto quanto deveria ser.
Alguma sugestão para uma maneira mais limpa e compacta de fazer isso? Precisaria funcionar tão antigo quanto ksh88
no AIX, Sun, HP-UX e Linux.
Observe que
A && B || C
executa C se A ou B falhar. Você precisa usarif
para separar B e C corretamente.Parece que você deseja criar uma função e provavelmente em um arquivo de biblioteca: se estiver em arquivo
my_timeout.ksh
Então, em seus scripts, a alteração mínima é:
O ksh
.
procurará no PATH os arquivos de origem (pelo menos no ksh93, não tenho 100% de certeza sobre o ksh88). Caso contrário, obtenha-o por caminho absoluto.Eu criaria um diretório
timeout
e:/bin/
e/usr/bin
)df
:(obviamente apenas para os comandos que você deseja ter um tempo limite)