producir comando df un sistema de archivos específico de gran total

7 minutos de lectura

avatar de usuario
emilio

Solo necesito hacer algo básico que podría manejar por mi cuenta, pero resultó que tengo dudas sobre el resultado que obtengo …

Necesito producir un total general usando el comando df en un sistema de archivos específico en dos servidores diferentes.

ssh server1 df -mP | egrep "/dev/md10|/dev/md11" | sort ; ssh server1 df -mP --total | grep "total" | egrep -v "/dev/md10|/dev/md11

El resultado:

/dev/md10                                                   183004016  87303581  95700436      48% /si001c1
/dev/md11                                                   183004016 165986430  17017587      91% /si001c2
total                                                       366565396 253332843 113232554      70%

Y luego usé el mismo comando en el segundo servidor para obtener el total general. Mi pregunta, el total general que obtengo no parece correcto (no estoy seguro) y cómo producir un total general combinando ambos usando el mismo comando de todos modos usando un comando de una sola línea o como un script básico en bash. Gracias por la ayuda.

Actualización: esta es una actualización después de seguir la guía de @EdmCoff.

printf "Grand total: " ; (ssh server1 df -m /dev/md11 ; ssh server2 df -m /dev/md1*) | awk 'a+=$2;b+=$3;c+=$4;d+=$5/3} END {print a" "b" "c" "d%}'

Resultado:

Grand total: 549012050 501832399 47179652 92%

Construyó un script (re-hecho):

#!/bin/bash
(ssh server1 df -m --no-sync "/dev/md11" ; ssh server2 df -m --no-sync "/dev/md1*") | sed -e /^Filesystem/d | sort > df_udsall
#(cat df_udsall)
printf "\nUDS:\nserver1 & server2\n"
printf "Mounted on       Free space   Disk usage   Use"%%"   Disk state"
while read df_udsall 
do
USAGE=$(echo $df_udsall ; echo $grand_total) | awk '{print $5}' | cut -d"%" -f1
if [[ "$USAGE" -ge " 95" ]]
then
STATUS='CRITICAL'
elif [[ "$USAGE" -ge " 90" ]]
then
STATUS='WARNING'
else
STATUS='OK'
fi
printf "$(echo $df_udsall | awk '{print $6, $4, $3, $5}' > df_udsall_stats)"
column -t df_udsall_stats | perl -ne 'chomp ; printf "\n%-18s %8s %12s %6s %-2s", split / +/' ; printf "`echo -ne $STATUS`"
done < df_udsall
printf "\n\nGrand total " ; cat df_udsall | awk '{b+=$4;c+=$3;d+=$5/3} END {print b" "c" "d "%"}' > grand_total
column -t grand_total | perl -ne 'chomp ; printf "%15s %12s %6s %-2s", split / +/' ; printf "`echo -ne $STATUS`"
rm -f df_udsall df_udsall_stats grand_total

El script anterior necesita algunos ajustes.

Resultado Esperado:

UDS:
server1 & server2
Mounted on         Free space   Disk usage   Use%   Disk state
/sic1                16202762    166801255    92%   WARNING
/sic2                15648157    167355860    92%   WARNING
/sic3                15256569    167747448    92%   WARNING

Grand total:         47107488    501904563    92%   OK

Se corrigió el resultado de salida del script tripleee:

UDS:
server1 & server2
Mounted on         Free space   Disk usage   Use%   Disk state
/sic001c1          92146461     90857556    50% OK
/sic001c2          16873531    166130486    91% WARNING
/sic001c3          16832710    166171307    91% WARNING
/sic001c4          16362388    166641629    92% WARNING

Grand total:       142215090    589800978     81 OK%

  • Habrá siempre ser un pequeño % del sistema de archivos reservado para el root usuario. Así que no es una sorpresa que su total no sume

    – Inian

    28 de diciembre de 2017 a las 5:38


  • Para combinar sus dos comandos para obtener un gran total, ¿ha considerado simplemente usar awk? Estoy imaginando algo como (command for server 1; command for server 2) | awk '/total/ {a+=$2;b+=$3;c+=$4} END {print a" "b" "c}'

    – EdmCoff

    28 de diciembre de 2017 a las 5:48

  • @EdmCoff gracias por el comando, pero sigo prefiriendo que algo más o menos obtenga los mismos resultados en ambos servidores como se mencionó anteriormente. No soy un tipo de Linux, pero me divierte jugar todos los días debido a mi curiosidad por probar algo diferente de otros sistemas operativos. intento ejecutar el comando (ssh server1 df -mP --total /dev/md1* ; ssh server2b df -mP --total /dev/md1*) | awk '/total/ {a+=$2;b+=$3;c+=$4} END {print a" "b" "c}' pero el resultado no es el esperado. Es bueno aprender algunos comandos nuevos que en realidad no sabía.

    – emilee

    28 de diciembre de 2017 a las 6:55


  • Lo siento, no entendí lo que querías decir con total general (pensé que querías combinar los totales de los dos servidores). Mi sugerencia sigue siendo incómoda, suponiendo que desee sumar las tres columnas simultáneamente. Asi que, ssh server1 df -mP /dev/md1* | awk '{a+=$2;b+=$3;c+=$4} END {print a" "b" "c}' (es decir, su comando sin que el total y la suma de todas las columnas) o ssh server1 df -mP --total /dev/md1* | awk '!/total/ {a+=$2;b+=$3;c+=$4} END {print a" "b" "c}' (es decir, incluya el total en su comando, pero exclúyalo en el comando awk).

    – EdmCoff

    30 de diciembre de 2017 a las 5:09

  • Si realmente quieres usar bc, te sugiero algo como ssh server1 df -mP /dev/md1* | tr -s ' ' | cut -d" " -f 2,2 | paste -sd+ - | bc donde estoy usando el tr comando para reemplazar múltiples espacios con un espacio, el cut comando para obtener sólo la segunda columna de números, el paste comando para reformatear la columna como num1+num2+num3+etcétera, y el bc comando para hacer los cálculos. Obviamente, necesitaría cambiar el comando de corte para cualquier columna que quisiera sumar.

    – EdmCoff

    30 de diciembre de 2017 a las 5:12

avatar de usuario
triplicado

Aquí hay un intento de refactorizar su secuencia de comandos en una versión en la que Awk tiene el control total de los cálculos y el formato de la salida, como se sugiere en varios comentarios. Tengo comentarios en línea que es posible que desee eliminar.

#!/bin/bash
# use a loop to reduce duplication of ssh options etc
while read -r server mounts; do
    ssh "$server" df -m --no-sync $mounts </dev/null
done <<\____SERVER__MOUNTS |
    server1 /dev/md10 /dev/md11
    server2 /dev/md12 /dev/md13
____SERVER__MOUNTS
# sed -e /^Filesystem/d inlined into Awk below
sort |
# pipe into awk
awk 'BEGIN { print "UDS:\nserver1 & server2"
        # Maybe use printf here too
        print "Mounted on         Free space   Disk usage   Use%   Disk state"
        fmt="%-18s %8i %12i %6s %-2s"
    }
    function status(num) {
        # Awk conveniently ignores any trailing string
        # so you can compare 95% to 95 numerically
        if (num > 95) result="CRITICAL"
        else if (num > 90) result="WARNING"
        else result="OK"
        return(result)
    }
    ! /^Filesystem/ {
        printf fmt "\n", $6, $4, $3, $5, status($5)

        # EdmCoff''s hack, too lazy to change to legible variable names
        # adapted to defer division until we know the final value of n
        a+=$2;b+=$3;c+=$4;dd+=$5;n++
    }
    END { d=dd/n;
        printf "\n" fmt "%%\n",
     "Grand total:", c, b, int(d), status(d) }'

Obviamente, no tengo forma de probar esto con una entrada real, por lo que probablemente haya errores menores de formato, etc. Espero haber capturado suficiente lógica para al menos mostrarle cómo implementar el cuerpo de este procesamiento como un script Awk.

Observe la ausencia de archivos temporales (que su secuencia de comandos original no podría limpiar si se interrumpiera; usar trap) y el uso de sangría para ayudarte a ver los bucles y condicionales.

  • gracias por el script pero no entiendo algunas de sus funciones lo que me da error. awk: cmd. línea: 12: (FILENAME=- FNR=1) fatal: no hay suficientes argumentos para satisfacer la cadena de formato `%-18s %8s %12s %6s %-2s %s ‘ ^ se agotó para este

    – emilee

    10 de enero de 2018 a las 7:45


  • Edité la respuesta para eliminar el final. %s preguntaste pero podría haber más; Obviamente no tengo manera de probar esto. Si puede proporcionar algunos datos de prueba realistas, no debería ser difícil eliminar los errores restantes.

    – triplete

    10 de enero de 2018 a las 7:46

  • El código Awk es una traducción uno a uno bastante sencilla de su script de shell, pero si hay algo en particular que no entiende, pregunte e intentaré aclararlo. Realmente solo extrae algunos campos de cada línea que no es un /^Filesystem/ línea y realiza los cálculos a partir de su código.

    – triplete

    10 de enero de 2018 a las 7:49

  • Ejecuté el script, se ve bien al principio. Luego me di cuenta de que el script no veía los dispositivos del servidor 2, solo mostraba el dispositivo del servidor 1. Cada servidor tiene 2 dispositivos. Así que cambié las líneas #6 y #7 server1 /dev/md10 /dev/md11 & server2 /dev/md12 /dev/md13, server1 OK pero no server2. Necesito que el porcentaje se redondee sin decimales y el umbral del estado del disco. Realmente no sé cómo poner eso junto.

    – emilee

    11 de enero de 2018 a las 1:59

  • Una mejor manera de calcular d sería 100.0*c/(c+b) pero dejaré esto como un comentario ahora.

    – triplete

    12 de enero de 2018 a las 6:09


¿Ha sido útil esta solución?