Estoy buscando una manera de limitar la cantidad de datos almacenados en una variable Bash que se inicializa a partir de la salida de un subproceso.
El problema con esta posible solución es que almacena la salida completa antes de truncarla.
#!/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
La alternativa OUT_DATA=$($COMMAND_TO_RUN | head -c 10000)
cancela el comando cuando se leen los primeros 10k de salida y necesito que el comando se ejecute hasta su finalización para capturar su estado de salida.
Puedo hacerlo bastante fácilmente en python
, pero espero una bash
única solución. Y además sin recurrir a la escritura en disco.
Respuesta1
Con una función. Para facilitar la lectura, el siguiente ejemplo codifica el comando y demás.
truncated_du() {
du / | { head -c 10000; cat >/dev/null; }
return "${PIPESTATUS[0]}"
}
out_data="$(truncated_du)"
out_result="$?"
head
pasa como máximo la cantidad deseada de datos a la salida estándar de la función. Si hay más datos, cat
los descartará sin interrumpir du
. El estado de salida de du
se recupera de la PIPESTATUS
matriz y la función lo devuelve.
Nota: mis variables usan lower case
; veresta respuesta.
Sin una función, la misma solución se ve así:
out_data="$(
du / | { head -c 10000; cat >/dev/null; }
exit "${PIPESTATUS[0]}"
)"
out_result="$?"
En mi opinión, es un poco menos legible de esta manera.
Respuesta2
Esto limita la cantidad que captura, pero supongo que sale con read
el estado de salida (no sé si detiene el comando como head
lo haría porque no se respeta el estado de salida: `
IFS= read -r -d '' -n $chars_to_capture foo < <($command)
Parece permitir que el comando se ejecute hasta su finalización, pero no obtiene el estado de salida del comando, obtiene read
el estado de salida, lo cual no es útil.
Un ejemplo
$ 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
Supongo que el hecho de que se toque el archivo significa que el comando no se interrumpe después de capturar la cantidad solicitada de caracteres.
Quizás podrías escribir el estado de salida en un archivo en el 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