Inventarisierungstool für Client-Hardware

Hallo Sascha,

ich habe mir jetzt eine Lösung gebastelt. die die Daten direkt auf dem
Server einfach aus den Linbo-Logs liest. Ich brauche allerdings auch
nicht so viele Angaben wie Du in Deinem Ansatz vorgelegt hast.

#!/bin/bash cd /var/log/linuxmuster/linbo/ echo
„Name;CPU;RAM;Platte;MAC1;MAC2“ for n in $(ls linbo.log) do
NAME=$(echo $n|cut -d
-f1) CPU=$(grep -m1 ’ CPU0’ $n |sed 's/.

CPU0:(.)[(]family./\1/') MEMORYK=$(egrep -m1 ‚^Memory‘ $n |sed
‚s/Memory: [0-9]K/([0-9])K./\1/')$ HDDSIZE=$(egrep -m1 'sda.GB’
$n | sed 's/.
[(]([0-9]
GB)./\1/') ETH0=$(egrep -m1
'eth0.
[0-9a-f]{2}:‘ $n | perl -pe 's/.([0-9a-f:]{17})./\1$
ETH1=$(egrep -m1 'eth1.[0-9a-f]{2}:’ $n | perl -pe
's/.
([0-9a-f:]{17}).*/$ if [[ ! -z $CPU ]]; then echo
„$NAME;$CPU;$MEMORYK;$HDDSIZE;$ETH0;$ETH1“ fi done |

… das ist pfiffig … Respect :slight_smile:

LG

Holger

Hallo Sascha,

Deine Idee, die schon auf dem Server liegenden LINBO-logs der Clients zu nutzen, ist sehr effizient!
Ich habe mir die Logs daraufhin mal genauer angesehen.

Bei mir liegen die LINBO-Logs allerdings nicht auf dem Server, sondern auf einem Cache-Server, da unser Server zu netzint ausgelagert ist. Außerdem hätte ich gerne mehr Infos über die Hardware, wie z.B. RAM-Riegel um z.B. die RAM-Aufrüstung mit meiner Schüler-AG zu planen. Ich werde daher einen ssh-Upload vom Client auf den Server weiter verfolgen.

Gruß,

Stefan

Hallo Stefan,
kann ich verstehen. Ich habe auch gerade gemerkt, dass mein Ansatz noch nicht der Weisheit letzter Schluss sein kann. In den Logs stehen nämlich für NVME-Platten keine Größen. Das ist im Moment kein Problem, weil wir nur in zwei Räumen so Platten haben und es mir nur um einen groben Überblick ging.
Außerdem erfasst das Skript natürlich nur die Rechner mit aktuellem Log, also nur Rechner die in den letzten 24 oder 48 Stunden eingeschaltet wurden…
Gruß
Sascha

Hi.
Bevor ihr alles selbst schreibt … es gibt auch noch dieses Tool:

…verlinkt wurde das hier: Linux + get the all information about the hardware from machine by tool or script - Server Fault – da gibt’s auch ein kleines Demo.

Hallo zusammen,

Danke für die Anregungen!

Das Datensammeln auf dem Client ist für mich soweit ausreichend gelöst mit meinem Script, welches auf dem Client läuft. Es macht eine Textzeile (mit semikolon-separierten Werten), die in eine csv-Datei geschrieben werden kann.
Jetzt bleibt noch der Aspekt, wie man eine sichere Übertragung der Textzeile auf Server gewährleistet.
Sascha hat dazu ja schon Tipps gegeben, die ich gut finde.

@Till : Sie hatten mir die Hook-Scripts nahe gebracht, mit denen ich client-side schon einiges gemacht habe - und so ganz auf den postsync verzichten konnte.

Ich hatte die Idee das das Datensammeln durch ein server-side hook script unter sysstart.sh starten zu lassen.

Meine Fragen:

  • Läuft so ein server-side hook script unter sysstart.sh als root A) auf dem Server - oder B) auf dem Client? Also erfasse ich mit meinem inventarisierungstool-Skript, wenn ich es so aufrufe, die Clientdaten oder die Serverdaten?
    – Falls A) auf dem Server:
    Könnte ein Skript auf dem Server dann das auf dem Client liegende inventarisierungstool-Skript starten und vom Server dann z.B. per ssh das Ergebnis vom Client GEHOLT werden?
    – Falls B) auf dem Client:
    Dann liegt das Skript selbst ja auf dem Server, wird aber auf dem Client ausgeführt. Könnte man dann so den Upload auf den Server per ssh machen über einen anderen Benutzer als root (so wie Sascha ja den User „hardwaresammler“ vorgeschlagen hat)?

Gruß,

Stefan

Hallo,

das Skript läuft jetzt als server-side hook script auf den Clients unter dem lokalen root-Konto gestartet am Ende des Bootvorgangs des Linux-Betriebssystems von sysstart.sh:
/var/lib/samba/sysvol/$server.$domain/scripts/$schoolname/custom/linux/sysstart.sh

Das Skript selbst liegt also nicht auf dem Client, sondern nur auf dem Server unter
/var/lib/samba/sysvol/$server.$domain/scripts/$schoolname/custom/linux/...

Der Upload in eine csv-Datei auf dem Server geschieht per ssh über einen extra dafür auf dem Server angelegten Benutzer in das Home dieses Benutzers. Nur dieser extra angelegte Server-Benutzer hat den PublicKey (also quasi das Schlüsselloch), Server-root also nicht.

Die ssh-Dateien (PublicKey und PrivateKey), die im Home des Client-root liegen müssen damit der Upload über den Server-Benutzer klappt, werden vom Skript temporärär dort hin kopiert, mit 400 Rechten versehen und danach wieder gelöscht.

Prinzipiell klappt es so - einige Befehle zum Infosammeln muss ich aber noch umschreiben.
Danke für die ssh-Tipps, die waren mir sehr nützlich.
Danke auch für die Hinweise auf versch. Sammeltools, aber leider konnte ich diese oder deren Code nicht für mich verwenden.

Frage: Wie seht ihr das Verfahren sicherheitstechnisch?

Gruß,

Stefan

Hi Stefan,
sicherheitstechnisch seh ich da keine größeren Probleme. Natürlich fühlt es sich komisch an, einen Nutzer am Server zu haben, für den der Key auf jedem Client liegt. Aber zunächst mal ist das auf dem Server ja nur ein „normaler“ Nutzer, der keine Root-Rechte hat (er ist ja hoffentlich kein sudoer). Und Du schreibst, dass Du nach dem Upload den Key sogar wieder weglöschst, dann kann den auch keiner abgreifen.
Wenn Du trotzdem noch paranoid bist solltest Du drauf achten, dass das Heimatverzeichnis des Users sowohl auf Client als auch Server nicht öffentlich, also 755 ist (das ist bei Ubuntu < 22.04 leider standardmässig so !).
Wenn Du dann immer noch paranoid bist, kannst Du dem Serveruser die Shell wegkonfigurieren oder (falls der scp dann nicht mehr funktioniert) ihm als Shell eine rbash (restricted bash) oder ähnliches zuweisen, also eine shell mit Einschränkungen.

Gruß
Sascha

Hallo,

hier mal die Ausgabe des Skriptes in einer ersten lauffähigen Version:

clientinfo_ce3c97a7a33d79b8835a4d076b831e95.csv

Zeit;Hostname;MAC-Cable;MAC-WiFi;IP;Marke;Typ;SerienNr;CPU;RAMtyp;RAMgesamt(MB);RAMmodule(MB);DISKsize(GB);DISKmarke;DISKmodell;LANkarte;Grafik;Audio;Distro;;PCI
2022-10-10___15:22:50;Ax007-pc12xx;f0:92:1c:de:8f:d6;;10.1.26.12;Hewlett-Packard;HP Compaq Elite 8300 CMT;CZC4031P4F;Intel Core i5-3470;DDR3;8192;4096 4096 No No;111.79;Kingston;SUV400S37120G;Intel 82579LM Gigabit Network;Intel Xeon E3-1200 v2/3rd Gen Core processor Graphics;Intel 7 Series/C216 Family High Definition Audio;Linux Mint 20.3 Una;;00:00.0 Host bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (rev 09) 00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09) 00:14.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller (rev 04) 00:16.0 Communication controller: Intel Corporation 7 Series/C216 Chipset Family MEI Controller #1 (rev 04) 00:16.3 Serial controller: Intel Corporation 7 Series/C210 Series Chipset Family KT Controller (rev 04) 00:19.0 Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection (Lewisville) (rev 04) 00:1a.0 USB controller: Intel Corporation 7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (rev 04) 00:1b.0 Audio device: Intel Corporation 7 Series/C216 Chipset Family High Definition Audio Controller (rev 04) 00:1d.0 USB controller: Intel Corporation 7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (rev 04) 00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev a4) 00:1f.0 ISA bridge: Intel Corporation Q77 Express Chipset LPC Controller (rev 04) 00:1f.2 SATA controller: Intel Corporation 7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] (rev 04) 00:1f.3 SMBus: Intel Corporation 7 Series/C216 Chipset Family SMBus Controller (rev 04)
2022-10-10___15:26:35;Sx105-pc01xx;00:0f:fe:6a:6e:46;;10.1.154.1;Hewlett-Packard;HP Compaq dc7700 Convertible Minitower;CZC71034XK;Intel Core2 6400;DDR2;3072;1024 1024 1024 No No;111.79;Kingston;SV300S37A120G;Intel 82566DM Gigabit Network;Intel 82Q963/Q965 Integrated Graphics;Intel 82801H HD Audio;Linux Mint 20.3 Una;;00:00.0 Host bridge: Intel Corporation 82Q963/Q965 Memory Controller Hub (rev 02) 00:02.0 VGA compatible controller: Intel Corporation 82Q963/Q965 Integrated Graphics Controller (rev 02) 00:03.0 Communication controller: Intel Corporation 82Q963/Q965 HECI Controller (rev 02) 00:19.0 Ethernet controller: Intel Corporation 82566DM Gigabit Network Connection (rev 02) 00:1a.0 USB controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Controller #4 (rev 02) 00:1a.1 USB controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Controller #5 (rev 02) 00:1a.7 USB controller: Intel Corporation 82801H (ICH8 Family) USB2 EHCI Controller #2 (rev 02) 00:1b.0 Audio device: Intel Corporation 82801H (ICH8 Family) HD Audio Controller (rev 02) 00:1c.0 PCI bridge: Intel Corporation 82801H (ICH8 Family) PCI Express Port 1 (rev 02) 00:1d.0 USB controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Controller #1 (rev 02) 00:1d.1 USB controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Controller #2 (rev 02) 00:1d.7 USB controller: Intel Corporation 82801H (ICH8 Family) USB2 EHCI Controller #1 (rev 02) 00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev f2) 00:1f.0 ISA bridge: Intel Corporation 82801HO (ICH8DO) LPC Interface Controller (rev 02) 00:1f.2 RAID bus controller: Intel Corporation SATA Controller [RAID mode] (rev 02)

Und hier der Code - so wie er bei uns läuft, ohne Gewähr…

Installationshinweise sind direkt im Skript.

#!/bin/bash

# onBoot-Skript linuxmuster.net 7.0
# clientinfo2csv.sh
#
# Vorbereitung des Skriptes siehe unten
#
# Sammelt Systeminformationen auf dem Clients und schreibt diese in eine csv-Datei auf dem Server.
# So entseht eine Tabelle mit Systeminformationen aller Clients.
#
# Linux Mint 20.3 Xfce 64bit
# 2022-10-10
# GPL v3
# Sen
# Tin



##### Infos zur Programmierung

### Semikolon wird als Zellentrenner in der csv verwendet

### Die Ausgabedatei enthält im Dateinamen eine Checksumme der Überschriften damit bei einem Update mit Änderung der Überschriften die Spaltenzuordnung der Werte weiterhin stimmt

### Folgendes ersetzt Semikolon durch Komma in den gesammelten Werten, da sonst Werte zusätzliche Zellen in der csv erzeugen könnten 
# | sed '{s/;/,/g}'

### Folgendes wandelt eine mehrzeilige Datei in einen Einzeiler um, sodass diese in der csv nur eine Zelle belegt
# readarray -t rammodules < /tmp/seninv-rammodules
# RAMmodules=$(echo ${rammodules[*]})

### Die Übertrageung auf dem Server wird durch SSH-Key abgesichert

### Ändert man die Überschriften für die csv-Datei, so wird eine neue csv-datei angelegt !!!!
# Das ist eine Vorsichtsmaßnahme, da die Spalten der bisherigen Einträge mit denen der geänderten Einträge evtl. nicht zusammenpassen könnten.




##### Vorbereitung des Skriptes

### Auf dem Server den Benutzer (ohne root-Rechte) "clientinfo" anlegen
# sudo adduser clientinfo --gecos ""

### Auf dem Client als root die ssh-keys erstellen und auf den Server kopieren für den Benutzer clientinfo
# ssh-keygen -t rsa -f ~/.ssh/id_rsa_seninv
# ssh-copy-id clientinfo@server

### Dieses Skript clientinfo2csv.sh auf den Server kopieren nach
# Pfadangabe: /var/lib/samba/sysvol/$server.$domain/scripts/$schoolname/custom/linux/clientinfo

### In dieses Skript kopieren:
# Den Inhalt vom Client-root ~/.ssh/id_rsa_seninv.pub kopieren zwischen in die Anfürungszeichen von PublicKey=""
# Den Inhalt vom Client-root ~/.ssh/id_rsa_seninv     kopieren zwischen in die Anfürungszeichen von PrivateKey=""

### Das Skript auf dem Server ausführbar machen 
# chmod +x /var/lib/samba/sysvol/$server.$domain/scripts/$schoolname/custom/linux/clientinfo/clientinfo2csv.sh

### Das Skript auf dem Server eintragen in das server-side hook script 
# nano /var/lib/samba/sysvol/$server.$domain/scripts/$schoolname/custom/linux/sysstart.sh
# Eintrag: sudo bash /var/lib/samba/sysvol/$server.$domain/scripts/$schoolname/custom/linux/clientinfo/clientinfo2csv.sh

### Sicherheit überprüfen auf dem Server
# Rechte 771 von /var/lib/samba/sysvol/$server.$domain/scripts/$schoolname/custom/linux/clientinfo/clientinfo2csv.sh
# Rechte 700 von /home/clientinfo/.ssh

### Die ssh-keys dürfen nur für die Benutzer root und clientinfo zugänglich sein! Also evtl. Arbeitskopie dieses Skripts auf dem Client löschen!



##### Systemanpassungen

### Serverangaben
# IP des Servers oder Servername (LMN7-Standard: server)
ServerIP="server"

### SSH-Konfiguration
# User für den der SSH-Key ist
ServerUser="clientinfo"

# PublicKey (hierher kopieren aus  ~/.ssh/id_rsa_seninv.pub)
PublicKey="ssh-abcabc"

# PrivateKey (hierher kopieren aus ~/.ssh/id_rsa_seninv)
PrivateKey="-----BEGIN OPENSSH PRIVATE KEY-----
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-----END OPENSSH PRIVATE KEY-----"





###### Progamm

###Zeitstempel
Zeit=$(date +%F___%T)

###Hostname
Host=$(hostname | sed '{s/;/,/g}')

###Herstellerinfo
#Marke
Marke=$(sudo dmidecode -s system-manufacturer  | sed '{s/;/,/g}')
#Typ
Typ=$(sudo dmidecode -s system-product-name | sed '{s/;/,/g}')
#Seriennummer
Sno=$(sudo dmidecode -s system-serial-number | sed '{s/;/,/g}')

###MAC
#WiFi
MACwifi=$(iw dev | grep addr | awk '{print $2}' | sed '{s/;/,/g}')
#Cable, falls kein WiFi
if [[ "$MACwifi" == "" ]]; then  
MACcable=$(ip addr | sed -ne '/link\/ether/{s/.*ether //;s/ .*//;p;}')
#Cable, falls WiFi vorhanden
else
MACcable=$(ip addr | sed -ne '/link\/ether/{s/.*ether //;s/ .*//;p;}' | sed "/$MACwifi/d")
fi

###IP
IP=$(hostname -I | awk '{print $1}')

###CPU
Cpu=$(sudo inxi -C -c 0 | sed -ne '/^CPU:/{s/.*model: //;s/ bits:.*//;p;q;}' | sed '{s/;/,/g}')

###RAM:
#Typ
sudo dmidecode -t memory | sed -ne '/DDR/{s/.*Type: //;s/ .*//;p;}' | uniq | sed '{s/;/,/g}' > /tmp/seninv-ramtype
readarray -t ramtype < /tmp/seninv-ramtype
RAMtype=$(echo ${ramtype[*]})
#Module
sudo dmidecode -t memory | sed -ne '/Size/{s/.*Size: //;s/ .*//;p;}' | sort | sed '{s/;/,/g}' > /tmp/seninv-rammodules
readarray -t rammodules < /tmp/seninv-rammodules
RAMmodules=$(echo ${rammodules[*]})
#RAMgesamt
RAMgesamt=$(awk '{sum+=$1}END{print sum}' /tmp/seninv-rammodules)

###Festplatte
#Größe
DISKsize=$(sudo inxi -D -c 0 | sed -ne '/vendor:/{s/.*size: //;s/ .*//;p;q;}' | sed '{s/;/,/g}')
#Marke
DISKmarke=$(sudo inxi -D -c 0 | sed -ne '/vendor:/{s/.*vendor: //;s/ model:.*//;p;q;}' | sed '{s/;/,/g}')
#Modell
DISKmodell=$(sudo inxi -D -c 0 | sed -ne '/vendor:/{s/.*model: //;s/ size:.*//;p;q;}' | sed '{s/;/,/g}')

###Netzwerkkarte
LANkarte=$(sudo inxi -N -c 0 | sed -ne '/^Network:/{s/.*Device-1: //;s/ driver:.*//;p;q;}' | sed '{s/;/,/g}')

###Grafik
Grafik=$(sudo inxi -G -c 0 | sed -ne '/^Graphics:/{s/.*Device-1: //;s/ driver:.*//;p;q;}' | sed '{s/;/,/g}')

###Audio
Audio=$(sudo inxi -A -c 0 | sed -ne '/^Audio:/{s/.*Device-1: //;s/ driver:.*//;p;q;}' | sed '{s/;/,/g}')



###OS
#Distro
Distro=$(sudo inxi -S -c 0 | sed -ne '/^System:/{s/.*Distro: //;s/.$//;p;q;}' | sed '{s/;/,/g}')



###PCI
sudo lspci | sed '{s/;/,/g}' > /tmp/seninv-pci
readarray -t pci < /tmp/seninv-pci
PCIinfo=$(echo ${pci[*]})



### Ausgabe in csv
# Werte
Werte="$Zeit;$Host;$MACcable;$MACwifi;$IP;$Marke;$Typ;$Sno;$Cpu;$RAMtype;$RAMgesamt;$RAMmodules;$DISKsize;$DISKmarke;$DISKmodell;$LANkarte;$Grafik;$Audio;$Distro;;$PCIinfo"

# Ueberschriften
Ueberschriften="Zeit;Hostname;MAC-Cable;MAC-WiFi;IP;Marke;Typ;SerienNr;CPU;RAMtyp;RAMgesamt(MB);RAMmodule(MB);DISKsize(GB);DISKmarke;DISKmodell;LANkarte;Grafik;Audio;Distro;;PCI"

# Checksumme der Überschriften erstellen
Checksum=$(md5sum <<< "$Ueberschriften")
Checksum=$(awk '{print $1}' <<< $Checksum)

# Ausgabedateiname anpassen auf Checksumme der Überschriften
Ausgabedatei="/home/$ServerUser/clientinfo_$Checksum.csv"

# SSH-keys hinterlegen für Client-root
mkdir -p ~/.ssh/ 2> /dev/null
echo "$PublicKey" > ~/.ssh/id_rsa_seninv.pub
echo "$PrivateKey" > ~/.ssh/id_rsa_seninv
echo "$PrivateKey" > ./id_rsa_seninv
chmod 400 ./id_rsa_seninv
chmod 400 ~/.ssh/id_rsa_seninv

# Zielpfad erstellen
ssh -i ./id_rsa_seninv -o StrictHostKeyChecking=accept-new -q $ServerUser@$ServerIP "mkdir -p $Ausgabepfad 2> /dev/null"

# Ausgabedatei mit Ueberschriften anlegen falls nötig
ssh -i ./id_rsa_seninv -o StrictHostKeyChecking=accept-new -q $ServerUser@$ServerIP [[ -f ""$Ausgabedatei"" ]] || echo ""$Ueberschriften"" | ssh -i ./id_rsa_seninv -o StrictHostKeyChecking=accept-new -q $ServerUser@$ServerIP -T "cat >> $Ausgabedatei"

# Falls Cable-MAC-Adresse in csv-Datei schon vorhanden,wird diese Wertezeile gelöscht
ssh -i ./id_rsa_seninv -o StrictHostKeyChecking=accept-new -q $ServerUser@$ServerIP -T "if grep -q ""$MACcable"" ""$Ausgabedatei""; then sed -i ""/.*""$MACcable"".*/d"" ""$Ausgabedatei""; fi"

# Werte kopieren
echo ""$Werte"" | ssh -i ./id_rsa_seninv -o StrictHostKeyChecking=accept-new -q $ServerUser@$ServerIP -T "cat >> $Ausgabedatei"



### Aufräumen
rm -f /tmp/seninv*
# SSH-keys löschen bei Client-root
rm -f ~/.ssh/id_rsa_seninv*
rm -f ./id_rsa_seninv

Der Code wurde zum Teil erstellt von einem meiner AG-Schüler.
Über Anmerkungen würden wir uns freuen!

Gruß,
Stefan

2 „Gefällt mir“

PS: Die Variablen in dem Pfad müssen noch definiert werden, je nach Eurer Konfiguration:
/var/lib/samba/sysvol/$server.$domain/scripts/$schoolname/custom/linux/

z.B:
/var/lib/samba/sysvol/linuxmuster.lan/scripts/default-school/custom/linux/

siehe auch:

Ja, so eine Inventur ist eine feine Sache. Danke, wenn sich dem jemand annimmt.

Frage: Warum nicht beispielsweise FusionInventory nehmen? Das füttert beispielsweise auch GLPI und GOSA. Man erspart sich vielleicht reichlich Arbeit und hat gleich noch mehr gelöst.

Hallo!
Als Nachtrag, da ich zufällig heute darüber gestolpert bin … einige hier nutzen ja checkMK als Monitoring-Tool. Das kann ebenfalls Hardware inventarisieren (auch wenn das eigentlich natürlich eher für Server und nicht für Workstations gedacht ist):

Viele Grüße
Michael