ubuntuusers.de

Zahlen in Datei auswerten und Datei dann ändern

Status: Ungelöst | Ubuntu-Version: Ubuntu 23.10 (Mantic Minotaur)
Antworten |

shiro Team-Icon

Supporter

Anmeldungsdatum:
20. Juli 2020

Beiträge: 1350

BrauchHilfe schrieb:

Raw Datei mit den NAS Werten:

1
2
3
4
5
$ cat nbdevquery1.txt
V_6_ OST_N_Pool NAS _PhysicalLSU @aaaax 712461.77 213294.57 99 1 0 1 0 1 14 0 0 0
V_6_ OST_S_Pool NAS _PhysicalLSU @aaaa1 712461.77 212883.59 70 1 0 1 1 2 14 0 0 0
V_6_ OST_N_Pool2 NAS _PhysicalLSU @aaaa5 712461.77 196844.52 81 0 1 1 1 14 0 0 0
V_6_ OST_S_Pool2 NAS _PhysicalLSU @aaaa9 712461.77 267027.98 62 1 0 1 0 2 14 0 0 0

Wenn man diese Datei verwendet und

gsub("V_6_ OST_N_Pool NAS _PhysicalLSU @aaaax", "NAS01")

die ganzen "gsub" sich sparen sowie die Felder in der Datei nicht abändern will, kann man die Suche nach "vorn" nehmen. In diesem Fall muss man auch nicht den Status aus der Pipe mit PIPESTATUS ermitteln.

Ich definiere mal das folgende Script als "nas.sh", dem man den gesuchten NAS Namen als 1.Parameter ($1) übergeben kann:

#!/bin/bash
# $1 = Name des NAS (Default: NAS1)
Name=${1:-"NAS01"}
awk -v q="$Name" 'BEGIN{
	n["@aaaax"]="NAS01";
	n["@aaaa1"]="NAS02";
	n["@aaaa5"]="NAS03";
	n["@aaaa9"]="NAS04"}
n[$5] == q {
	if ($8 >= 90) {sts="CRITICAL"; e=2} 
	else { 
		if ($8 >=80) {sts="WARNING"; e=1} 
		else { sts="OK";e=0 }
	}
	print sts" - "n[$5]" - "$8" % used Capacity out of "$6/1024" TiB|free Capacity in TiB="$7/1024";"$6/1024*0.2";"$6/1024*0.1
	exit e
}' nbdevquery1.txt

Dann bekommt man bei folgendem Aufruf die gezeigte Ausgabe mit Exit-Status.

$ for nas in NAS01 NAS02 NAS03 NAS04; do
 echo "--- $nas ---"
 . nas.sh $nas
 echo "Exit-Code=$?"
done
--- NAS01 ---
CRITICAL - NAS01 - 99 % used Capacity out of 695.763 TiB|free Capacity in TiB=208.295;139.153;69.5763
Exit-Code=2
--- NAS02 ---
OK - NAS02 - 70 % used Capacity out of 695.763 TiB|free Capacity in TiB=207.894;139.153;69.5763
Exit-Code=0
--- NAS03 ---
WARNING - NAS03 - 81 % used Capacity out of 695.763 TiB|free Capacity in TiB=192.231;139.153;69.5763
Exit-Code=1
--- NAS04 ---
OK - NAS04 - 62 % used Capacity out of 695.763 TiB|free Capacity in TiB=260.77;139.153;69.5763
Exit-Code=0
$ 

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4747

Wohnort: Berlin

@homer65: Beim öffnen von Textdateien sollte man die Kodierung angeben. Sonst muss man hoffen, dass das zur Datei passt was da ”geraten” wird.

Die Namen sind fast alle schlecht. satz steht nicht für einen Satz, worte steht nicht für Worte, test nicht für einen Test, und das awort gehört sich nicht. rc ist eine übliche Abkürzung für „radio controlled“.

Das rstrip() ist überflüssig. int() stört sich nicht an „whitespace“ vor und/oder nach der Zahldarstellung.

Für den Rückgabecode solle man Konstanten definieren und keine magischen Zahlen in den Quelltext schreiben.

Falls im Programmablauf eine Ausnahme vorkommt die nicht behandelt wird, haben wir den Rückgbabecode nicht mehr in der Hand, da sollte man sich also unbedingt selbst drum kümmern.

Werte und Zeichenketten mit + zusammenstückeln ist eher BASIC als Python. Zumal print() selbst ja Leerzeichen zwischen mehrere Argumente setzt. Es ist auch unschön da aufsteigende Indexzugriffe manuell zu schreiben. Entweder benutzt man da die Syntax um eine Sequenz auf Argumente aufzuteilen beim Aufruf, oder noch besser, man bindet die einzelnen Werte an sprechende Namen, damit der Leser weiss, was das bedeutet.

Es fehlt der Import von exit() aus dem sys-Modul. Das exit() auch einfach so existiert ist ein Artefakt vom interaktivien Interpreter. Darauf darf man sich in Programmen nicht verlassen.

Ungetestet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env python3
import logging
import sys

OK, WARNUNG, KRITISCH, UNBEKANNT = range(4)


def main():
    rueckgabe_code = UNBEKANNT
    try:
        with open("nas_free.txt", encoding="ASCII") as datei:
            rueckgabe_code = OK
            for zeile in datei:
                name, gesamt_text, frei_text, belegt_text = zeile.split()
                plattenbelegung = int(belegt_text[3])
                if plattenbelegung >= 90:
                    antwort = "KRITISCH"
                    rueckgabe_code = KRITISCH
                elif plattenbelegung >= 80:
                    antwort = "WARNING"
                    if rueckgabe_code not in {KRITISCH, UNBEKANNT}:
                        rueckgabe_code = WARNUNG
                else:
                    antwort = "OK"
                
                print(name, gesamt_text, frei_text, antwort)
    except:
        logging.excepttion("UNBEKANNT")
        rueckgabe_code = UNBEKANNT
    
    sys.exit(rueckgabe_code)


if __name__ == "__main__":
    main()

@BrauchHilfe: In Deinem Shell-Skript ist ein nutzloses cat. awk kann man den Dateinamen geben.

Statt *nach* der Verarbeitung zu testen ob $Name gesetzt ist, könnte man das einfach *vorher* auf den Default-Wert setzen, der dann ersetzt wird oder eben auch nicht.

Was soll denn der erste Doppelpunkt beim getopts-Argument?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/bin/bash
Help()
{
   echo "Monitoring Capacity of NAS Storage"
   echo
   echo "Syntax: $(basename "$0") [-q|h]"
   echo "options:"
   echo "-q     insert one of the NAS devices - NAS01 ... NAS04"
   echo "-h     Print this Help."
   echo
}

Name=NAS
while getopts "hq:" option; do
   case $option in
      h) # display Help
         Help
         exit;;
      q) # Enter a name of the NAS
         Name=$OPTARG;;
      *) # Invalid option
         echo "Error: Invalid option"
         Help
         exit;;
   esac
done

awk '{ 
    gsub("V_6_ OST_N_Pool NAS _PhysicalLSU @aaaax", "NAS01")
    gsub("V_6_ OST_S_Pool NAS _PhysicalLSU @aaaa1", "NAS02")
    gsub("V_6_ OST_N_Pool2 NAS _PhysicalLSU @aaaa5", "NAS03")
    gsub("V_6_ OST_S_Pool2 NAS _PhysicalLSU @aaaa9", "NAS04");
    if ($4 >= 90) {
        $5="CRITICAL"
    } else {
        if ($4 >=80) {
            $5="WARNING"
        } else {
            $5="OK"
        }
    }
    print $5" - "$1" - "$4" % used Capacity out of "$2/1024" TiB|free Capacity in TiB="$3/1024";"$2/1024*0.2";"$2/1024*0.1
}' nbdevquery1.txt | grep "$Name"

In Python mit Rückgabecode (ungetestet):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env python3
import logging
import sys
from argparse import ArgumentParser
from enum import Enum

INFO_FILENAME = "nbdevquery1.txt"
PREFIX_TO_NAS_NAME = {
    "V_6_ OST_N_Pool NAS _PhysicalLSU @aaaax": "NAS01",
    "V_6_ OST_S_Pool NAS _PhysicalLSU @aaaa1": "NAS02",
    "V_6_ OST_N_Pool2 NAS _PhysicalLSU @aaaa5": "NAS03",
    "V_6_ OST_S_Pool2 NAS _PhysicalLSU @aaaa9": "NAS04",
}
CRITICAL_LIMIT = 90  # in %.
WARNING_LIMIT = 80  # in %.


class State(Enum):
    OK = 0
    WARNING = 1
    CRITICAL = 2
    UNKNOWN = 3

    def updated(self, new):
        return self if new.value < self.value else new


def main():
    try:
        parser = ArgumentParser(
            description="Monitoring capacity of NAS storage"
        )
        parser.add_argument(
            "nas_name",
            metavar="NAS",
            default="NAS",
            nargs="?",
            help=(
                f"Name of NAS from {', '.join(PREFIX_TO_NAS_NAME.values())}"
            ),
        )
        arguments = parser.parse_args()

        with open(INFO_FILENAME, "r", encoding="ASCII") as lines:
            check_count = 0
            result_state = State.OK
            for line in lines:
                for prefix, nas_name in PREFIX_TO_NAS_NAME.items():
                    if arguments.nas_name in nas_name and line.startswith(
                        prefix
                    ):
                        total_capacity, free_capacity, used_percent = map(
                            float, line[len(prefix) :].split()[:3]
                        )
                        if used_percent > CRITICAL_LIMIT:
                            state = State.CRITICAL
                        elif used_percent > WARNING_LIMIT:
                            state = State.WARNING
                        else:
                            state = State.OK

                        result_state = result_state.updated(state)

                        print(
                            f"{state.name} - {nas_name} - {used_percent}% used"
                            f" capacity out of {total_capacity / 1024} TiB"
                            f"|free capacity in TiB={free_capacity / 1024}"
                            f";{total_capacity / 1024 * (1 - WARNING_LIMIT / 100)}"
                            f";{total_capacity / 1024 * (1 - CRITICAL_LIMIT / 100)}"
                        )
                        check_count += 1
                        break

            if check_count == 0:
                result_state = State.UNKNOWN
                print(f"{arguments.nas_name} not found.")
    except:
        logging.Exception("Huh?")
        result_state = State.UNKNOWN

    sys.exit(result_state.value)


if __name__ == "__main__":
    main()

BrauchHilfe

(Themenstarter)

Anmeldungsdatum:
24. April 2024

Beiträge: 5

Dann bekommt man bei folgendem Aufruf die gezeigte Ausgabe mit Exit-Status.

$ for nas in NAS01 NAS02 NAS03 NAS04; do
 echo "--- $nas ---"
 . nas.sh $nas
 echo "Exit-Code=$?"
done
--- NAS01 ---
CRITICAL - NAS01 - 99 % used Capacity out of 695.763 TiB|free Capacity in TiB=208.295;139.153;69.5763
Exit-Code=2
--- NAS02 ---
OK - NAS02 - 70 % used Capacity out of 695.763 TiB|free Capacity in TiB=207.894;139.153;69.5763
Exit-Code=0
--- NAS03 ---
WARNING - NAS03 - 81 % used Capacity out of 695.763 TiB|free Capacity in TiB=192.231;139.153;69.5763
Exit-Code=1
--- NAS04 ---
OK - NAS04 - 62 % used Capacity out of 695.763 TiB|free Capacity in TiB=260.77;139.153;69.5763
Exit-Code=0
$ 

Hi shiro, ...das gefällt mir sehr gut....Grund für den "cat.....|grep" am Ende war, dass ohne Eingabe einer NAS alle vier NAS Systeme angezeigt werden. Muss noch einmal nachdenken, ob ich das überhaupt brauche....sonst nehm ich deine Lösung. Im Monitoring muss ich dann den Schalten "-q" noch herausnehmen, weil in deiner Lösung bracht man diesen Schalter nicht mehr. Vielen Dank....muss noch mal drüber nachdenken

Antworten |