Bash - Command&Control-Script

Ein neuer Artikel wurde veröffentlicht
  • Hey zusammen.


    Ich hab mir hier ein Script gemacht um eine Gruppe von Raspberrys mit identischer Softwarekonfiguration gleichzeitig oder einzeln Anzusprechen um bestimmte vordefinierte Befehle auszuführen.


    Um die Clients anzusprechen habe ich ein txt-File auf einem Webserver gespeichert welche dann von den Clients heruntergeladen und ausgewertet wird. Um zu verifizieren dass die Befehle von mir kommen habe ich noch eine Berechnung für einen Verifizierungscode eingebaut welcher stetig wechselt. Somit sollte verhindert werden dass jemand anderes die Clients ansprechen kann.


    Es können (so hoffe ich) auch nicht direkt Befehle in die txt-Datei eingetragen werden da die zeilen jeweils mit einem remote_ zu beginn ausgeführt werden.

    Shell-Script
    1. while IFS= read -r var
    2. do
    3. remote_$var
    4. done < $COMMANDLIST

    Beispielausgabe bei "sudo reboot": remote_sudo reboot = error

    Besipielausgabe Funktion: remote_setusr pi = Ok


    Ich habe jetzt keine spezifische Frage zum Script selber sondern eher ob ich da irgend ein Überlegungsfehler gemacht habe bzw ob da bei dieser Methode evt Probleme auftreten könnten an welche ich noch nicht gedacht habe.


    EDIT: Ja es gibt fertige Lösungen. Ich möchte jedoch meine Fertigkeiten im Programmieren etwas festigen und hab mir schon länger überlegt was für ein "sinnvolles" Script ich schreiben könnte. Falls mein Ansatz nicht völlig für die Tonne ist bevorzuge ich eine DIY-Lösung.


    Grüsse Apop


    Wer sich das Script etwas genauer ansehen will:

    Ich suche nicht nach einer fertigen Lösung sondern nach dem Weg dahin ;)

    Dieser Beitrag wurde bereits 8 Mal editiert, zuletzt von Apop85 ()

  • Hey Dani


    Ja hab ich noch vergessen zu erwähnen :) . Ich dachte mir schon dass es da fertige Lösungen gibt nur hab ich schon länger überlegt was für ein Script ich machen könnte was brauchbar ist und ich während dem schreiben optimalerweise noch was lernen könnte ;) 


    Falls mein Ansatz völlig für die Tonne ist würd ich ggf auf eine fertige Lösung ausweichen.


    Grüsse Apop

  • Dein Weg mag vielleicht funktionieren, für ein Anfänger auch schon ziemlich gut umgesetzt, aber Ich würde lieber darüber nachdenken auf Python zu wechseln und bash wegzulassen.

    Zum einen sind die Möglichkeiten über bash sehr beschränkt du musst dich größtenteils auf externe Befehle verlassen, zum anderen ist die Performance nicht gerade berauschend zumal du sehr wenig mit bash Built-in Befehlen machst, und die Reaktionszeit beträgt bei deiner Umsetzen mindestens eine Minute. Zu guter letzt ist das Debuggen oder allg. abfangen von Fehlern eher umständlich in bash.


    Ich hatte früher auch ein sehr großes Projekt welches ich primär in bash umgesetzt hatte - auch Server/Client basierend. Wenn ich das Projekt heute kriegen würde, oder die Zeit hätte es noch mal neu zu programmieren, würde ich kein bash mehr nutzen ;)


    Über Python könntest du zum Beispiel einen Socket_Server programmieren wohin sich die Clients verbinden - inkl. Authorisierung, also eine Umsetzung eines eigenen Protokolls (hört sich schwerer an als es ist). Der läuft permanent und reagiert auch sofort.

    Oder du nutzt bottle um einen Webserver einzusetzen, brauchst dann aber keine extra Textdatei sondern nimmst dann zB nur ein Dictionary und übermittelst die Informationen zum Client in JSON.


    Wenn du dich damit aber absolut gar nicht anfreunden kannst: Wenn du Wert auf Sicherheit legst wäre ein optimalere Weg über SSH bzw genauer gesagt sshpass... Dh der Server verbindet sich zu den Clients via SSH und führt den gewünschten Befehl dort selber aus. Das hätte den Vorteil dass du auf den Clients kein extra Script einrichten musst und auch keinen Webserver für die Clients... Das einzige was du einrichten bräuchtest (nicht zwangsweise) wären SSH-Keys.


    In deiner gather_status Funktion würde ich sonst die Abfrage ob ein Prozess läuft verbessern... Zum einen fragst du jedes mal erneut ps ax ab was übertrieben ist, zum anderen würde sich statt ps eher pgrep -x anbieten ;)


    Generell verwendest du sehr viele PIPE's was aber teilweise gar nicht nötig ist... Zum Beispiel kann grep auch zählen dafür bedarf es nicht zusätzlich wc, oder check=$(cat $COMMANDLIST) wäre schneller: check=$(< $COMMANDLIST)

    oder if [ "$check" != "" ]; then würde ich lieber so machen: if [ -n "$check" ]; then

  • Hey meigrafd Danke für dein Feedback. Und ja ich sollte wirklich mal von Bash weg kommen :) . Ich greiffe teilweise nach jedem verfügbaren Strohhalm (viele Pipes ^^ ). Denke werde für den Anfang mal einen Passwortgenerator in py probieren, sollte relativ basic sein. Denke direkt mit einem Socket_Server zu beginnen wäre wohl etwas too much, vorallem auch durch die wahrscheinlich häufiger vorkommenden Rückfragen an die Community ^^ . Oder stell ich mir das grad schwerer vor als es tatsächlich ist ;) ?


    Bezüglich Reaktionszeit habe ich z.Z. sogar einen Stundentakt im Sinn (Zumindest bei diesem Entwicklungsstand des Scripts, da auch noch keine Prüfung integriert ist ob schon ein Run mit dem vorliegenden Code durchgeführt wurde). Für Aufgaben die Zeitnah gelöst werden sollen werde ich sicherlich noch SSH bevorzugen. Den Code den ich für die Verifizierung generiere ist jeweils eine Stunde gültig und kann auch vorausberechnet werden. Ich kann z.b. auch einen Code für ein bestimmtes Datum und eine Bestimmte Zeit generieren und so die Ausführung des Scripts bzw die Befehle von remote.txt so timen dass diese irgendwann mitten in der Nacht durchgeführt werden. Beispielcodes: [21bfd612] [2357c2e9]


    check=$(cat $COMMANDLIST) war noch ein Artefakt welches inzwischen obsolet wurde da die remote.txt automatisch immer mit passendem Verifizierungscode und Userdefinition generiert wird. Hab das nun in check=$(grep -c '' $COMMANDLIST) geändert und das Ausführen an die Bedingung gehängt dass mindestens 3 Zeilen in remote.txt vorhanden sein müssen.


    Danke für den Tipp mit pgrep -x ;) werd mir das gleich mal anschauen.


    Bezüglich Sicherheit stellt sich mir vorallem die Frage ob jemand die remote.txt so ändern könnte dass Fremdcode ausgeführt werden kann oder ob das mit dem remote_$var "sicher" ist. (Das wäre dann Codeinjection o.ä. wenn ich mich recht entsinne).


    llutz Danke für den Tipp :) 

  • Das sieht doch schon sehr gut aus :thumbup:meigrafd hat noch verschiedene mögliche Optimierungen erwähnt. Aber meist geht es in bash nicht darum schnellen Code sondern funktionierenden Code zu schreiben. Und durch die Menge der Tools unter Linux gibt es diverse Möglichkeiten ein bestimmtes Problem zu lösen - speziell wenn man die kleinen Tülchen per pipes kombiniert. Aber Du willst ja auch lernen und dann solltest Du Dir seine Hinweise schon zu Herzen nehmen :)


    Auch könnte man 'Prüfe Services' in eine Loop bei Benutzung eines Arrays umwandeln. Die ist dann sehr leicht zu erweitern.


    Wichtig ist auch rechtzeitig den Absprung zu finden. Wenn abzusehen ist dass ein SW-Projekt größer wird ist der Rat von bash wegzugehen absolut richtig,

  • Sicherlich kann man sich darüber streiten was wie wo besser aussehen könnte, oder einer macht es lieber so der nächste völlig anders...


    Performance kann auch mit Bash eine Rolle spielen - insbesondere bei eher schwachbrüstigen Systemen: läuft auf dem System zB KODI welches gerade einen HD-Film wiedergibt und im Hintergrund arbeitet ein bash Script, was aber leider zwischendurch hohe CPU Auslastung verursacht, kann das zu unangenehmen Rucklern bei der Wiedergabe führen....


    Man kann auch in bash ObjektOrientiertProgrammieren und zum Beispiel Funktionen & Einstellungen in extra Dateien auslagern, und dann via source einbinden.


    Guck dir zB auch mal die EPSPi.sh hier an: http://raspberrypi.roxxs.org/EPSPi/

    (das Script ist auch schon steinalt)

  • Übliches Szenario ist bei mir dass ich mal eben eine kleine Aufgabe mit bash lösen möchte und es so runterschreibe. Es funktioniert dann perfekt mit den Testdaten und auch im normalen Betrieb. Dann plötzlich vervielfacht sich z.B. die Menge der Daten und plötzlich dauert alles zu lange. Dann ist es Zeit sich den bash Code genauer anzusehen und zu optimieren. Falls das immer noch nicht reicht muss dann leider eine andere schnellere Sprache her. Oder wie Du schreibst hat man neuen/anderen Load auf seinem System der durch intensive bash Aktionen Performanceprobleme bekommt wie bei der HD Wiedergabe und muss dann noch mal optimieren.


    OO bash? Habe ich noch nie gesehen :no_sad:. Hast Du Beispielcode? Mit dem cfront hat Stroustrup ja auch C OO Fähigkeiten beigebracht indem aus C++ Code C Code generiert wurde. Theoretisch kann man sowas ja auch mit bash machen - also aus bash++ reinen bash Code generieren. Aber das macht wohl nur ein Compilermasochist :lol:

  • OO bash? Habe ich noch nie gesehen :no_sad:. Hast Du Beispielcode?

    Google nur mal nach OO bash :fies::angel:



    Beispiel:


    /usr/local/etc/config.cfg

    Shell-Script
    1. Benutzer="meigrafd"
    2. Pass=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)


    /usr/local/bin/karl

    Shell-Script
    1. #!/bin/bash
    2. source /usr/local/etc/config.cfg
    3. echo "Benutzername $Benutzer mit Password $Pass"


    /usr/local/bin/heinz

    Shell-Script
    1. #!/bin/bash
    2. source /usr/local/bin/karl
    3. echo Ciao

    chmod +x /usr/local/bin/heinz


    Test:


    :cool:


    Normalerweise macht man das zwar nicht so sondern zB mit Funktionen/Klassen, aber ist ja nur ein Beispiel ;)



    Besseres Beispiel:


    /usr/local/bin/functions.sh

    Shell-Script
    1. function abc() {
    2. echo abc!
    3. }
    4. function xyz() {
    5. local get=$1
    6. [ "$get" == "user" ] && echo $Benutzer
    7. [ "$get" == "pass" ] && echo $Pass
    8. }


    /usr/local/bin/heinz

    Shell-Script
    1. #!/bin/bash
    2. source /usr/local/etc/config.cfg
    3. source /usr/local/bin/functions.sh
    4. abc
    5. xyz "pass"
    6. xyz "user"
    7. echo $Pass
  • Ich muss gestehen dass dieses mir so abwegig erschien dass ich nicht mal versucht habe zu suchen :blush:


    Dabei habe ich dieses gefunden was mir als ein halbwegs praktiabler Ansatz erscheint. Allerdings ist das dann alles primär über Namenskonventionen erschlagen. Wie dann Inheritance, Poloymorphie, Scoping usw möglich ist steht da nicht und da suche ich jetzt auch nicht nach da das eher eine akademische Sache ist und aus meiner Sicht keine praktische relevanz hat.

    Letztendlich ist das aber noch viel schlimmer als der OO Aufsatz in Python, der ja auch nachtraeglich reingebracht wurde - wie auch in vielen anderen Sprachen. Interessant ist der Ansatz schon - aber eher für akademische theoretische Betrachtungen. Ich glaube kaum dass sich jemand so viel Arbeit macht bash++ zu schreiben :lol:


    Zu Deinem Beispiel: Das ist eine haeufig gebrauchte Methode um größeren bash Codebestand in kleine reusable Componenten und Funktionen zu zerlegen. Quasi die C include files. Aber ein Beispiel für OO ist es nicht. Deshalb war ich ja auch etwas verwundert und habe nachgefragt.