Estou procurando uma maneira de limitar a quantidade de dados armazenados em uma variável Bash que é inicializada a partir da saída de um subprocesso.
O problema com esta solução potencial é que ela armazena toda a saída antes de truncá-la.
#!/bin/bash
COMMAND_TO_RUN="du /"
OUT_DATA=$($COMMAND_TO_RUN)
OUT_RESULT=$?
if [[ $OUT_RESULT -ne 0 ]]; then
echo "${OUT_DATA:0:10000}" | head mail -s "Command failed" [email protected]
fi
A alternativa OUT_DATA=$($COMMAND_TO_RUN | head -c 10000)
cancela o comando quando os primeiros 10k de saída são lidos e preciso que o comando seja executado até a conclusão para capturar seu estado de saída.
Posso fazer isso facilmente python
, mas espero uma bash
única solução. E também sem recorrer à gravação em disco.
Responder1
Com uma função. Para facilitar a leitura, o exemplo abaixo codifica o comando e tal.
truncated_du() {
du / | { head -c 10000; cat >/dev/null; }
return "${PIPESTATUS[0]}"
}
out_data="$(truncated_du)"
out_result="$?"
head
passa no máximo a quantidade desejada de dados para o stdout da função. Se houver mais dados, cat
irá descartá-los sem interromper du
. O status de saída de du
é recuperado do PIPESTATUS
array e retornado pela função.
Nota: minhas variáveis usam lower case
; veresta resposta.
Sem uma função a mesma solução fica assim:
out_data="$(
du / | { head -c 10000; cat >/dev/null; }
exit "${PIPESTATUS[0]}"
)"
out_result="$?"
IMO é um pouco menos legível dessa forma.
Responder2
Isso limita a quantidade que você captura, mas presumo que ele saia com read
o status de saída (não sei se para, para o comando como head
faria porque o status de saída não é respeitado: `
IFS= read -r -d '' -n $chars_to_capture foo < <($command)
Parece permitir que o comando seja executado até a conclusão, mas você não obtém o status de saída do comando, obtém read
o status de saída, o que não é útil.
Um exemplo
$ IFS= read -r -d '' -n 19 foo < <(seq 50; touch somefile; exit 42); echo "exit=$?"; ls -l somefile
exit=0
-rw-r--r-- 1 glennjackman staff 0 Jul 22 22:04 somefile
Presumo que o fato de o arquivo ser tocado significa que o comando não será interrompido após a captura do número solicitado de caracteres.
Talvez você possa escrever o status de saída em um arquivo no subshell:
IFS= read -r -d '' -n 10000 out_data < <( $command_to_run; echo $? > statusfile )
if [[ -f statusfile ]] && [[ "$(<statusfile)" != "0" ]]; then
printf "%s\n" "$out_data" | head mail -s "Command failed" [email protected]
rm statusfile
fi