Este script permite poner en un archivo las últimas N líneas de una salida. Por ejemplo, ping [...] | alwayslast.bash FILE 10 permitiría que FILE tuviera las últimas 10 líneas de la salida de ping.
This script allows for a file to have the las N lines of an output. For example, ping [...] | alwayslast.bash FILE 10 would make FILE always have the last 10 lines from the output of ping.
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Usage: $0 output_file maxlines"
exit 2
fi
FILE="$1"
MAXLINES="$2"
START=0
LINES=1
while IFS= read -r NEWLINE; do
BUFFER[START]="$NEWLINE"
TEMPFILE=$(mktemp)
trap -- 'rm "$TEMPFILE"' EXIT INT TERM
for INDEX in $(seq "$((START+1))" "$((LINES-1))") $(seq 0 "$START"); do
printf '%s\n' "${BUFFER[$INDEX]}"
done > "$TEMPFILE"
chmod --reference="$FILE" "$TEMPFILE"
mv "$TEMPFILE" "$FILE"
trap -- EXIT INT TERM
LINES="$((LINES+1))"
if [ "$LINES" -gt "$MAXLINES" ]; then
LINES="$MAXLINES"
fi
START="$(((START + 1) % MAXLINES))"
done
Gracias a Eduardo Bustamante por sus correcciones.
OUCH… Suena correcto, pero MUY gastalón 🙂
¿Por qué no usas una implementación ampliamente conocida y difundida? Digamos… El comando «last»?
$ genera_salida –larga –demasiado | last -15
Tail (por la sintaxis veo que te referías a tail) sólo arroja las últimas líneas de un stream cerrado. (–follow tampoco es útil en este caso).
Alwayslast.bash va consumiendo la entada estándar de un stream abierto y va exportando a un archivo las que hasta el momento son las últimas N líneas, remplazando el contenido en cada actualización para que queden sólo las últimas N líneas.
Caso de uso: no querer esperar a que corran 30 pings para obtener sus estadísticas sino usar los últimos 30 de un ping que ya está en ejecución como fuente de datos.