Anzeige:
Seite 5 von 6 ErsteErste ... 3456 LetzteLetzte
Ergebnis 61 bis 75 von 76

Thema: Syntax-Problem mit bash-Script

  1. #61
    Registrierter Benutzer
    Registriert seit
    17.12.2007
    Beiträge
    40
    Vielen Dank, Jan, für deine Hilfe!

    Hab dir soeben mal das Script per PN geschickt

    Eigentlich funktioniert jetzt alles soweit, bis auf die Option -z $option, die beim Parameter Start folgenden Fehler ausgibt:

    Code:
    h852677:~# ./DeinScript_new start
    + path_shoutcast=/home/shoutcast
    + use_screen=1
    + use_user=0
    + username=shoutcast
    + check_root=1
    + '[' '(' 0 -eq 0 ')' -a '(' 1 -eq 1 ')' -a '(' 0 -ne 1 ')' ']'
    + echo -ne '\033[0;31mWARNING\033[0m Server wird mit Superuser-Rechten gestartet, was ein enormes Sicherheitsrisiko darstellt...\nBitte gewuenschte Option waehlen:\n\n1) Startvorgang fortsetzen\n2) Startvorgang abbrechen\n\nOption: '
    WARNING Server wird mit Superuser-Rechten gestartet, was ein enormes Sicherheitsrisiko darstellt...
    Bitte gewuenschte Option waehlen:
    
    1) Startvorgang fortsetzen
    2) Startvorgang abbrechen
    
    Option: + read option
    
    + '[' '(' -ne 1 ')' -o '(' -z ')' ']'
    ./DeinScript_new: line 31: [: `)' expected, found 1
    ++ pgrep -f /home/shoutcast/sc_serv
    ++ pgrep -u shoutcast -f /home/shoutcast/sc_serv
    + '[' '(' -z '' -a 0 -eq 0 ')' -o '(' -z '' -a 0 -eq 1 ')' ']'
    + '[' 1 -eq 1 ']'
    + '[' 0 -eq 1 ']'
    + screen -dmS sc1 /home/shoutcast/sc_serv
    + '[' 0 -eq 0 ']'
    + echo 22035
    + echo -ne '\033[0;32mDONE\033[0m Server wurde gestartet\n\033[0;32mDONE\033[0m PID-File wurde erfolgreich angelegt\n'
    DONE Server wurde gestartet
    DONE PID-File wurde erfolgreich angelegt
    + exit 0
    Ja das stimmt, man könnte das Startscript gleich unter dem richtigen Benutzer öffnen, allerdings ist das ja oft nicht im wirklichen Einsatz der Fall und man öffnet dieses auch gerne mal als Root oder mit einem anderen User, oder es ist aus einem bestimmten Grund gar nicht möglich, das Script direkt unter einem bestimmten User zu öffnen, wobei man sich ja dann trotzdem keine Angst machen muss, da es ja die Option use_user gibt.

    MfG
    Michael

  2. #62
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Fireball22 Beitrag anzeigen
    ...Hab dir soeben mal das Script per PN geschickt
    Schau ich mir nachher an.

    Zitat Zitat von Fireball22 Beitrag anzeigen
    Eigentlich funktioniert jetzt alles soweit, bis auf die Option -z $option, die beim Parameter Start folgenden Fehler ausgibt:
    Das Problem ist hier, dass Du abprüfst, ob die Variable leer ist - wenn sie leer ist, dann steht da aber nix mehr, es fehlt also das Argument. Simple Lösung: ... -z "$option" ..., so kommt immer etwas an.

    Jan

  3. #63
    Registrierter Benutzer
    Registriert seit
    17.12.2007
    Beiträge
    40
    Okay super, ich freu mich schon auf deine Lösung!

    Das mit dem -z "$option" habe ich gerade ausgebessert, allerdings scheint er damit immer noch einen Fehler zu haben:

    Code:
    + '[' '(' -ne 1 ')' -o '(' -z '' ')' ']'
    ./DeinScript_new: line 31: [: `)' expected, found 1
    ++ pgrep -f /home/shoutcast/sc_serv
    ++ pgrep -u shoutcast -f /home/shoutcast/sc_serv
    + '[' '(' -z '' -a 0 -eq 0 ')' -o '(' -z '' -a 0 -eq 1 ')' ']'
    + '[' 1 -eq 1 ']'
    + '[' 0 -eq 1 ']'
    + screen -dmS sc1 /home/shoutcast/sc_serv
    + '[' 0 -eq 0 ']'
    + echo 8122
    + echo -ne '\033[0;32mDONE\033[0m Server wurde gestartet\n\033[0;32mDONE\033[0m PID-File wurde erfolgreich angelegt\n'
    DONE Server wurde gestartet
    DONE PID-File wurde erfolgreich angelegt
    MfG
    Michael

  4. #64
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Fireball22 Beitrag anzeigen
    ...Das mit dem -z "$option" habe ich gerade ausgebessert, allerdings scheint er damit immer noch einen Fehler zu haben:

    Code:
    + '[' '(' -ne 1 ')' -o '(' -z '' ')' ']'
    Schau Dir mal diesen Teil an: '(' -ne 1 ')' - was fällt auf? Richtig, da steht ein -ne 1 Operator + Operand mutterseelenallein im Wald rum, wo doch -ne ein binärer Operator ist und 2 Operanden haben will, einen vorne und einen hinten. Auch hier schlägt wieder die Falle zu, dass $option nicht gequotet ist - das musst Du prinzipiell immer machen, wenn Du nicht sicher weisst, dass eine Variable einen Inhalt hat.

    Ausserdem wirst Du auf die Nase fallen, wenn Du z. B. "X" eingibst, da bringt der numerische Test einen Syntaxfehler. Du willst ja die Eingabe nicht wirklich auf einen numerischen Wert abprüfen, sondern nur wissen, ob der Anwender das Zeichen "1" eingegeben hat, also solltest Du hier den alphanumerischen Operator "=" verwenden.

    Wenn Du sauber quotest, kannst Du sogar die -z-Prüfung wegfallen lassen:
    Code:
    jan@jack:~/tmp> x=
    jan@jack:~/tmp> if [ $x -ne 1 -o -z $x ]; then echo nok; fi
    bash: [: too many arguments
    jan@jack:~/tmp> if [ $x -ne 1 -o -z "$x" ]; then echo nok; fi
    bash: [: too many arguments
    jan@jack:~/tmp> if [ "$x" -ne 1 -o -z "$x" ]; then echo nok; fi
    bash: [: : integer expression expected
    jan@jack:~/tmp> if [ -z "$x" -o ! "$x" = "1" ]; then echo nok; fi
    nok
    jan@jack:~/tmp> if [ ! "$x" = "1" ]; then echo nok; fi
    nok
    Ein anderer Trick (geht aber nur bedingt, weil ein Buchstabe immer noch Fehler bringt):
    Code:
    jan@jack:~/tmp> if [ 0$x -ne 1 ]; then echo nok; fi
    nok
    Jan

  5. #65
    Registrierter Benutzer
    Registriert seit
    17.12.2007
    Beiträge
    40
    Vielen Dank für die Tipps!
    Genau so funktioniert es wohl am besten, wenn man diese direkt als alphanumerische Werte vergleicht!
    Das ist echt ne ziemlich große Umstellung wenn man nebenbei auch noch ständig mit PHP arbeitet, da sind doch etliche Unterschiede drin

    Mein stop-force-Teil sieht bis jetzt so aus und funktioniert auch ohne Probleme, sollte da noch eine Abfrage rein, ob der Server bereits läuft, oder sollte man bei der Force-Methode generell alle Möglichkeiten offen lassen?

    Code:
    stop-force)
                    echo -ne "Beende Prozesse mit Superuser-Rechten...\nGebe Prozesse Chance sich sauber zu beenden..."
                    su -c "pkill -f \"${path_shoutcast}/sc_serv\""
                    if [ $? -eq 0 ]; then
                            success=1
                    fi
                    su -c "sleep 5"
                    echo "Zwinge noch laufende Prozesse sich zu beenden..."
                    su -c "pkill -9 -f \"${path_shoutcast}/sc_serv\""
                    if [ $? -eq 0 -o $? -eq 1 ]; then
                            success=1
                    fi
    
                    if [ ${success} -eq 1 ]; then
                            echo -ne "\033[0;32mDONE\033[0m Server wurde erfolgreich heruntergefahren\n"
                            rm -f "${path_shoutcast}/server.pid"
                    else
                            echo -ne "\033[0;31mERROR\033[0m Server konnte nicht ordnungsgemaess heruntergefahren werden...\nBitte Debug-Modus starten...\n"
                    fi
            ;;
    MfG
    Michael

  6. #66
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Fireball22 Beitrag anzeigen
    ...Mein stop-force-Teil sieht bis jetzt so aus und funktioniert auch ohne Probleme, sollte da noch eine Abfrage rein, ob der Server bereits läuft, oder sollte man bei der Force-Methode generell alle Möglichkeiten offen lassen?...
    naja, auch bei "Brute-Force"-Attacken macht es wenig Sinn, etwas killen zu wollen, was nicht existiert, oder?

    So, ich habe meine Version fertig - so viele Kommentare habe ich selten in einem Script ;-) Folgende Dateien sind im anhängenden tar enthalten:
    shoutcast_orig.sh - Dein Originalscript (ich hoffe, Du hast nichts dagegen, es macht sich besser zum Vergleichen der Unterschiede)
    shoutcast.sh - meine Version
    sc_serv - ein kleines Shellscript, das Unsinn auf der Konsole ausgibt und beim Versuch, es zu erlegen, empört aufschreit um dann eine zufällige Wartezeit zwischen 1 und 10 Sekunden vor dem exit einzulegen (um den Ablauf kill - warten - kill -9 testen zu können). Habe ich gebastelt, um was zum Testen zu haben.

    Wundere Dich nicht über das geänderte Erscheinungsbild. Ich habe die Einrückungen von 8 auf 2 Leerzeichen verringert, weil mir sonst im vim zu schnell die Zeilen überlaufen. Aus dem gleichen Grund habe ich auch an einigen Stellen die Zeilen umgebrochen. Das ist aber reine Kosmetik und Geschmackssache und soll keine Empfehlung für Deinen Programmierstil darstellen. Unter diese Rubrik fällt auch das Ersetzen einiger "####..."-Zeilen durch Leerzeilen.

    Die wichtigsten inhaltlichen Änderungen:
    - Ich habe einige mehrfach benutzte Code-Abschnitte in Funktionen ausgelagert, um den Main-Teil übersichtlicher zu halten und Wiederholungen zu vermeiden
    - Die Sicherheitsabfrage beim Start durch root habe ich ebenfalls in eine Funktion ausgelagert, die anzuzeigende Meldung in eine Variable am Anfang des Scripts gepackt und die Abfrage der Eingabe in eine Schleife gelegt, die bei Fehleingaben eine Meldung bringt und erneut abfragt.
    - Beim Start per screen habe ich gemerkt, dass das Kommando immer 0 als Returncode liefert - egal wie das Ergebnis des Starts ist. Deshalb frage ich in diesem Fall per pgrep ab, ob der Prozess tatsächlich läuft.
    - Vor alle "su -c"-Aufrufe habe ich zusätzliche Meldungen gesetzt, wenn der aufrufende Benutzer nicht root ist - damit er weiss, wessen Passwort er dann einzugeben hat.
    - Das Erzeugen eines PID-Files habe ich rausgeschmissen - es wird nirgends ausgewertet und bringt deshalb nur unnötige potenzielle Fehlerquellen ins Script.
    - Im Stop habe ich am meisten umgebaut. Hier macht es wenig Sinn, die eingebauten Schalter auszuwerten, es kommt allein darauf an, unter welcher User-ID der Serverprozess läuft und damit, ob und wie ich ihn killen kann (der Start kann ja mit ganz anderen Parametern erfolgt sein).
    - Die Usage-Meldung bei ungültigem Aufruf habe ich an die allgemein übliche Syntax angepasst.
    - Ich habe einen trap am Anfang der Hauptroutine eingebaut, um eine entspr. Meldung anzuzeigen und mit einem passenden Returncode auszusteigen - auch um mal zu demonstrieren, wie man diese nützliche Funktion verwendet.
    - Die Returncodes des Scripts habe ich erweitert - sind am Anfang kommentiert.
    - statt pkill benutze ich zum Stoppen den einfachen kill. Da pgrep mir bereits die zutreffenden PIDs liefert, ist es unnötig, dann nochmal den pkill per regex über die ganze Prozessliste zu jagen, kill mit den PIDs ist mit Sicherheit schneller.
    - Die "kill ...; sleep 5; kill -9 ..."-Sequenz habe ich durch eine Warteschleife ersetzt, die pro Sekunde einmal guckt, ob noch Serverprozesse laufen. Nur wenn nach 5 Sekunden der sc_serv noch lebt, wird er per kill -9 ins Jenseits befördert.

    So, viel Spaß beim Vergleichen ;-) Ach ja - ich habe zwar alle möglichen Varianten getestet, lege aber meine Hand nicht dafür ins Feuer, dass ALLES fehlerfrei ist. Dazu müsste man sich dann doch noch ein paar Stunden hinsetzen und systematisch alle Wege durch das Script abklappern.

    Jan

    P.S.: Wenn Du Dein Script unter GPL stellen willst, dann kannst Du Änderungen von mir gern übernehmen.

  7. #67
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    noch 3 Hinweise zum stop-force:
    1. Warum rufst Du den sleep per "su -c" auf? Schlafen kann jeder ;-)
    2. Warum steigst Du nicht aus, wenn der erste kill bereits erfolgreich war?
    3. Wenn Du beim Aufruf mit "stop-force" zum Anfang abprüfst, ob der Aufrufer root ist, dann kannst Du alle "su -c" sparen. Andernfalls muss der Anwender bei jedem "su -c" das root-Passwort eingeben, da ist es doch viel bequemer, wenn er gleich "su -c 'shoutcast.sh stop-force'" aufruft - dann muss er das nur einmal tun.

    Jan

  8. #68
    Registrierter Benutzer
    Registriert seit
    17.12.2007
    Beiträge
    40
    Wow, vielen Dank für deine Mühe!
    Das ist ja echt heftig, was du hier zusammengeschrieben hast!

    Ich bin das jetzt mal die letzten Tage alles durchgegangen und habe mir das alles angeschaut, alles durchprobiert, geschaut, wie du das angestellt hast und dann in meinem Script verbessert und noch einige kleine Fehler ausgebessert.

    Die Idee mit den Funktionen ist echt super, aber leider ist mir das dann irgendwie zu unübersichtlich, weil ich ja dann speziell für jeden Fall in der Funktion etwas speziell definieren müsste.
    Ohne Funktionen hat es zwar klar den Nachteil, dass ca. 10 gleiche Zeilen vorkommen, aber dafür find ich das schon etwas übersichtlicher
    Ich hoff du bist mir da nicht böse, dass ich das nicht ganz so verwenden werde.

    Aber die Idee mit den Schleifen ist echt super und das habe ich auch alles direkt gleich alles angepasst.

    Die Code-Teile für die PID-Files sind ebenfalls nun komplett draußen und die Usage-Ausgabe habe ich ebenfalls überarbeitet.

    Ich bin vorhin zufällig im Internet noch auf eine Seite gestoßen, wo Scripte angeboten werden, die anhand einer PID-File feststellen, ob ein Server bereits gestartet bzw. beendet ist.
    Deshalb habe ich mir gedacht, dass ich dann auch zum Download die PID-Variante anbieten werde.
    Vllt. findet ja jemand damit Verwendung, auch wenn diese nicht wirklich zuverlässig ist.

    Zum stop-force:
    Wieso ich da noch nicht direkt aussteige, hat den Grund, dass pkill unter Umständen zwei Prozesse beenden muss. Einmal den eigentlichen Server-Prozess und noch den screen.
    Es reicht schon ein gekillter Prozess aus, damit er den Return-Code 0 zurückgibt, obwohl noch gar nicht alles beendet wurde.
    Deshalb killt er dann mit dem Signal -9 im Folgenden den Rest.
    Und das mit dem su -c bei sleep stimmt zwar, aber diese Funktion ist ja speziell dazu da, weil sich der Server mit weniger Rechten bzw. auf Ebene !ANDERER! Benutzer nicht mehr killen lässt. Nehmen wir an, auf der Ebene des !ANDEREN! Benutzers gibt es einen totalen Crash, wodurch auch nichts mehr richtig ausgeführt werden kann, dann bleibt er trotzdem bei sleep 5 hängen.
    Das ist zwar ein Fall, der warscheinlich kaum bis nie vorkommen wird, aber da setzte ich ja dann lieber einfach mal ein weiteres su -c.
    Ich hoffe mein Gedankengang war soweit richtig... *g*

    Eins muss ich hier auch noch hinzufügen:

    Code:
    pkill -u $username -f "${path_shoutcast}/sc_serv"
    Musste von mir durch folgendes Ersetzt werden, da ich in einigen Tests mit verschiedenen Benutzern festgestellt habe, dass er unter einem anderen Benutzernamen, der ungleich $username entspricht, eine Fehlermeldung ausbringt und nicht nach dem Passwort von $username fragt. Er killt deshalb a auch keine Prozesse. So funktioniert es ohne Probleme:
    Code:
    su -c "pkill -u $username -f \"${path_shoutcast}/sc_serv\"" $username
    Ich werde mich jetzt noch naher gleich ransetzten und die letzten Seite von meiner Page anpassen, dann könnt ihr euch das finale Script gerne anschauen und nochmals durchtesten.
    Wenn es noch irgendwelche Probleme geben sollte, dann wäre es super, wenn ihr die noch kurz postet =)

    MfG
    Michael

  9. #69
    Registrierter Benutzer
    Registriert seit
    17.12.2007
    Beiträge
    40
    So, nun ist es endlich soweit - bis jetzt sind gestern mehr als 4 Stunden Arbeit vergangen, bis endlich das ganze Download-Script funktioniert und die restlichen Fehler bei den letzten Tests behoben wurden:

    http://www.michis-homepage.net/scripting.php

    Ich würde mich sehr freuen, wenn ihr euch die Realtime-Version und die PID-Version nochmal anschauend würdet und auf evtl. Fehler überprüfen könntet.

    Vor allem hoffe ich nun auch, dass die stop-Funktion überall problemlos funktioniert, wo du (Jan) mir ja bereits mitgeteilt hast, dass da was noch nicht stimmt...

    MfG
    Michael
    Geändert von Fireball22 (03-02-2008 um 12:37 Uhr)

  10. #70
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Fireball22 Beitrag anzeigen
    ...Die Idee mit den Funktionen ist echt super, aber leider ist mir das dann irgendwie zu unübersichtlich, weil ich ja dann speziell für jeden Fall in der Funktion etwas speziell definieren müsste.
    Den Satz verstehe ich nicht ;-) Funktionen sollen Codeteile kapseln, die an mehreren Stellen benutzt werden (oder die Main-Funktion zu unübersichtlich machen). Daher sollen sie eigentlich der Übersichtlichkeit dienen. Wenn zu viele Parameter übergeben werden müssen oder zu viele Abhängigkeiten von globalen Variablen auftreten, dann kapsele ich eben noch mal - eine Funktion kann prima von einer anderen Funktion aufgerufen werden (habe ich ja mit der show_msg-Funktion schon gezeigt).

    Natürlich muss man sich beim Code-Lesen daran gewöhnen, dass es Code-Teile gibt, in die man reinhüpft. Ohne diese Art von strukturierter Programmierung ist man aber bei jedem etwas größeren Projekt erschossen, darum sollte man sich daran so schnell wie möglich gewöhnen. Vergleiche z. B. mal den Aufwand, wenn Du die Farbe einer "ERROR"-Meldung in Deiner und in meiner Version ändern willst. In meiner Version ist es exakt 1 Zeile - und bei Dir?

    Zitat Zitat von Fireball22 Beitrag anzeigen
    ...Ich hoff du bist mir da nicht böse, dass ich das nicht ganz so verwenden werde.
    Ich bin Dir nicht böse, ich habe nur Vorschläge gemacht. Es ist Dein Script.

    Zitat Zitat von Fireball22 Beitrag anzeigen
    Ich bin vorhin zufällig im Internet noch auf eine Seite gestoßen, wo Scripte angeboten werden, die anhand einer PID-File feststellen, ob ein Server bereits gestartet bzw. beendet ist.
    Deshalb habe ich mir gedacht, dass ich dann auch zum Download die PID-Variante anbieten werde.
    Vllt. findet ja jemand damit Verwendung, auch wenn diese nicht wirklich zuverlässig ist.
    Naja, das könnte eigentlich nur dann sein, wenn pgrep & Co. nicht installiert sind. Dann solltest Du das aber auch abprüfen, z. B. so:
    Code:
    if test -z "`which pgrep`"; then ...
    Es macht keinen Sinn, eine unsichere Variante eines Scripts anzubieten, wenn eine bessere existiert.

    Zitat Zitat von Fireball22 Beitrag anzeigen
    Zum stop-force:
    Wieso ich da noch nicht direkt aussteige, hat den Grund, dass pkill unter Umständen zwei Prozesse beenden muss. Einmal den eigentlichen Server-Prozess und noch den screen. Es reicht schon ein gekillter Prozess aus, damit er den Return-Code 0 zurückgibt, obwohl noch gar nicht alles beendet wurde.
    Deshalb killt er dann mit dem Signal -9 im Folgenden den Rest.
    OK, ist zwar unlogisch (siehe man screen, Abschnitt DESCRIPTION - ich habe bei meinen Tests nie einen übrig gebliebenen screen entdecken können) aber vielleicht tritt der Fall mal auf - aber wieso lässt Du Dir dafür 5 Sekunden Zeit und prüfst nicht erstmal, ob noch was zum Killen da ist?

    Zitat Zitat von Fireball22 Beitrag anzeigen
    Und das mit dem su -c bei sleep stimmt zwar, aber diese Funktion ist ja speziell dazu da, weil sich der Server mit weniger Rechten bzw. auf Ebene !ANDERER! Benutzer nicht mehr killen lässt. Nehmen wir an, auf der Ebene des !ANDEREN! Benutzers gibt es einen totalen Crash, wodurch auch nichts mehr richtig ausgeführt werden kann, dann bleibt er trotzdem bei sleep 5 hängen.
    Das ist zwar ein Fall, der warscheinlich kaum bis nie vorkommen wird, aber da setzte ich ja dann lieber einfach mal ein weiteres su -c.
    Ich hoffe mein Gedankengang war soweit richtig... *g*
    Naja, für mich nicht nachvollziehbar %-/ Völlig unabhängig davon, was Du vorher oder nachher machst (und mit welchem User das passiert), macht "sleep 5" einfach nur 5 Sekunden Pause. Der "su -c" rundrum ist und bleibt unsinnig!

    Zitat Zitat von Fireball22 Beitrag anzeigen
    Eins muss ich hier auch noch hinzufügen:

    Code:
    pkill -u $username -f "${path_shoutcast}/sc_serv"
    Musste von mir durch folgendes Ersetzt werden, da ich in einigen Tests mit verschiedenen Benutzern festgestellt habe, dass er unter einem anderen Benutzernamen, der ungleich $username entspricht, eine Fehlermeldung ausbringt und nicht nach dem Passwort von $username fragt. Er killt deshalb a auch keine Prozesse. So funktioniert es ohne Probleme:
    Code:
    su -c "pkill -u $username -f \"${path_shoutcast}/sc_serv\"" $username
    Stimmt - deshalb habe ich ja in meinem Script nicht pkill, sondern kill mit den PIDs aufgerufen, und dies immer mit mit dem User, der auch das Recht zum Killen hat (also im Zweifel per "su -c"). Du machst hier wieder Deinen klassischen Denkfehler: Du killst nur die Prozesse, die dem $username-Benutzer gehören - das bringt Dir aber überhaupt nichts, wenn das Script beim Start mit der Konfig-Einstellung use_user=0 aufgerufen wurde - dann gibts nur einen sc_serv, der unter einem völlig anderen User läuft (nämlich dem, der das Script gestartet hat). Den erwischst Du mit dieser Konstruktion nicht (kriegst auch keinen Fehler) und kannst anschließend auch keinen neuen Prozess starten, weil nämlich immer noch einer auf dem konfigurierten TCP-Port hängt.

    Rate mal, warum ich keinen "stop-force" in mein Script eingebaut habe: Nachdem ich mich mal intensiv mit Deinem Script auseinandergesetzt hatte, als ich meine Version aufgebaut habe, habe ich nämlich gesehen, dass das überflüssig ist. Dazu dient in meinem Script in der stop_server-Funktion die Abfrage, ob ich einen laufenden Prozess killen kann. Wenn ich das nicht kann, dann gebe ich die Meldung aus, dies doch mal unter root zu versuchen. Entweder ich kann die Prozesse killen oder nicht. Es spielt keine Rolle, wie die Konfig ausieht - wenn ich einen laufenden Prozess nicht killen kann, dann ist das ein Fehler, der Server läuft nämlich danach noch!!!

    Jan

  11. #71
    Registrierter Benutzer
    Registriert seit
    17.12.2007
    Beiträge
    40
    Vielen Dank nochmals für deine Tipps & deine Hilfe!

    Die su -c um die sleep 5 herum sind nun komplett weg, das würde eig. echt keinen wirklichen Sinn machen.
    Ich habe mir auch gerade Gedanken um die Warteschleife gemacht, allerdings würde das für den Anwender teilweise ja nur unnütze Arbeit bedeuten, in dem er ständig das für den User benötigte Passwort eingibt:

    Code:
    wait_cnt=1
      while test -n "`pgrep -f \"$path_shoutcast/sc_serv\"`"; do
        wait_cnt=`expr $wait_cnt + 1`
        test $wait_cnt -gt 5 && break
        sleep 1
      done
    Das muss er zwar in dieser Code-Konstellation noch nicht, aber allerdings würde das hier auch alles "greppen", und nicht nur die sc_serv des bestimmten Users.

    Und folgendes dient jetzt noch dazu, PID-Files zu verwenden, falls pgrep nicht installiert ist:

    Code:
    if [ -z "`which pgrep`" ]; then
            use_pid=1
    else
            use_pid=0
    fi
    Code:
    test "$use_pid" -eq 0 && if [ \( -z "`pgrep -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 0 \) -o \( -z "`pgrep -u $username -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 1 \) ]; then
                    test "$use_pid" -eq 1 && if [ ! -e "${path_shoutcast}/server.pid" ]; then
    Allerdings beschwert er sich dann über ein "unexpected ;;", d. h. über das Ende der Start-Funktion.

    Wo liegt denn da der Fehler, oder kann man das allgemein nicht so machen und mann muss den ganzen Code-Teil extra aufrollen?

    Stimmt - deshalb habe ich ja in meinem Script nicht pkill, sondern kill mit den PIDs aufgerufen, und dies immer mit mit dem User, der auch das Recht zum Killen hat (also im Zweifel per "su -c"). Du machst hier wieder Deinen klassischen Denkfehler: Du killst nur die Prozesse, die dem $username-Benutzer gehören - das bringt Dir aber überhaupt nichts, wenn das Script beim Start mit der Konfig-Einstellung use_user=0 aufgerufen wurde - dann gibts nur einen sc_serv, der unter einem völlig anderen User läuft (nämlich dem, der das Script gestartet hat). Den erwischst Du mit dieser Konstruktion nicht (kriegst auch keinen Fehler) und kannst anschließend auch keinen neuen Prozess starten, weil nämlich immer noch einer auf dem konfigurierten TCP-Port hängt.
    Jetzt versteh ich das ganze!
    Okay, ich hab mir gerade eben mal die Parameter von pgrep angeschaut und da scheint es leider keine Möglichkeit zu geben, die UID des Prozesses rauszufinden um ihn dann mit den entsprechenden Userrechten zu killen.
    Geht dass dann nur mit Root?

    Und das ganze betrifft aber dann nur den Aufruf, wenn $use_user = 0 ist, oder?
    Das andere alles läuft ohne Probleme? =)

    Okay, und wegen des stop-force werde ich gleich nochmal nachschauen

    MfG
    Michael

  12. #72
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Fireball22 Beitrag anzeigen
    ...Ich habe mir auch gerade Gedanken um die Warteschleife gemacht, allerdings würde das für den Anwender teilweise ja nur unnütze Arbeit bedeuten, in dem er ständig das für den User benötigte Passwort eingibt:
    Nein, das muss er nicht (wie Dein Codeblock ja zeigt) und die Abfrage nach den Prozessen aller User ist doch ok - beim Stoppen müssen alle weg.

    Zitat Zitat von Fireball22 Beitrag anzeigen
    Und folgendes dient jetzt noch dazu, PID-Files zu verwenden, falls pgrep nicht installiert ist:...
    Wo liegt denn da der Fehler, oder kann man das allgemein nicht so machen und mann muss den ganzen Code-Teil extra aufrollen?
    Mach lieber ne saubere if - then - else Abfrage, dann sieht der Code auch gleich lesbarer aus :-) Und teste die Existenz des PID-Files bitte nicht mit -e; der sagt Dir nicht, ob das tatsächlich eine Datei ist und ob Du sie auch lesen kannst.

    Zitat Zitat von Fireball22 Beitrag anzeigen
    Okay, ich hab mir gerade eben mal die Parameter von pgrep angeschaut und da scheint es leider keine Möglichkeit zu geben, die UID des Prozesses rauszufinden um ihn dann mit den entsprechenden Userrechten zu killen.
    Das ginge z. B., indem Du die gefundenen PIDs per ps auswertest, der hat entsprechende Optionen:
    Code:
    jan@jack:~/tmp> ps -o user= -o pid= -p `pgrep bash`
    jan       7122
    jan       7130
    Zitat Zitat von Fireball22 Beitrag anzeigen
    Und das ganze betrifft aber dann nur den Aufruf, wenn $use_user = 0 ist, oder?
    Nein, das ist ja gerade der springende Punkt: Wenn Du stop aufrufst, musst Du immer die Prozesse aller Benutzer berücksichtigen. Du weisst ja nicht, wie Dein Script beim vorigen Start aufgerufen wurde. Es ist völlig wurscht, wie Dein Script beim stop parametrisiert wurde, Du willst einen bestehenden sc_serv killen. Und dabei musst Du erstmal davon ausgehen, dass er unter einem beliebigen User laufen kann. Genau deshalb habe ich die Stop-Funktion so erweitert, dass alle möglichen Fälle (sc_serv gehört mir, sc_serv gehört $username, sc_serv gehört einem anderen User) separat behandle.

    Jan

  13. #73
    Registrierter Benutzer
    Registriert seit
    17.12.2007
    Beiträge
    40
    So, okay, da werde ich dann wohl den ganzen Abend noch rumbasteln & alles durchtesten.

    Allerdings habe ich noch eine Frage wie ich das am besten mit der If-Anweisung anstelle, weil dann hätte ich den größten Teil des Codes doppelt, selbst wenn ich das ganze in eine Funktion packe, habe ich einige Zeilen doppelt.
    Aber da muss es doch eine Möglichkeit geben, dass alles in eine If-Anweisung zu packen, oder?

    Sinngemäß müsste ungefähr so ausschauen, wie ich das aber in Echt anstelle weiß ich leider echt noch nicht... hmmm...
    Code:
    if [ ($use_pid = 0 -a(DANN) pgrep...) -o ($use_pid = 1 -a ! -e PID-FILE) ]; then
    Ich habe mir schon fast gedacht, dass ich das irgendwie so machen könnte:

    Code:
    if [ -z "`which pgrep`" ]; then
            use_pid=1
            if_start='! -e \"${path_shoutcast}/server.pid\"'
    else
            use_pid=0
            if_start='\( -z "`pgrep -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 0 \) -o \( -z "`pgrep -u $username -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 1 \)'
    fi
    und hier dann so:
    Code:
    if [ $if_start ]; then
    Das wäre immerhin eine Möglichkeit?
    Nur leider bekomme ich folgende Fehlermeldung:
    Code:
    h852677:~/bash-scripting# ./shoutcast-control start
    + path_shoutcast=/home/shoutcast
    + use_screen=1
    + use_user=1
    + username=shoutcast
    + check_root=1
    ++ which pgrep
    + '[' -z /usr/bin/pgrep ']'
    + use_pid=0
    + if_start=\( -z "`pgrep -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 0 \) -o \( -z "`pgrep -u $username -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 1 \)
    + '[' '(' 0 -eq 0 ')' -a '(' 1 -eq 1 ')' -a '(' 1 -ne 1 ')' ']'
    + '[' '\(' -z '"`pgrep' -f '\"${path_shoutcast}/sc_serv\"`"' -a '$use_user' -eq 0 '\)' -o '\(' -z '"`pgrep' -u '$username' -f '\"${path_shoutcast}/sc_serv\"`"' -a '$use_user' -eq 1 '\)' ']'
    ./shoutcast-control: line 57: [: too many arguments
    + echo -ne '\033[0;31mERROR\033[0m Server scheint bereits online zu sein...\n'
    ERROR Server scheint bereits online zu sein...
    + exit 1
    Aber wie gesagt, gäb es da vllt. eine Möglichkeit das ganze in eine Anweisung zu packen?

    MfG
    Michael

    EDIT:

    So, jetzt hab ich das ganze nochmal durchdacht und bin auf folgende If-Anweisung bekommen, die rein theoretisch alles genau so erfüllen müsste, wie ich mir das vorstelle =)
    Allerdings kommt folgendes dabei raus:
    Code:
    h852677:~/bash-scripting# ./shoutcast-control start
    + path_shoutcast=/home/shoutcast
    + use_screen=1
    + use_user=1
    + username=shoutcast
    + check_root=1
    ++ which pgrep
    + '[' -z /usr/bin/pgrep ']'
    + use_pid=0
    + '[' '(' 0 -eq 0 ')' -a '(' 1 -eq 1 ')' -a '(' 1 -ne 1 ')' ']'
    ++ pgrep -f /home/shoutcast/sc_serv
    ++ pgrep -u shoutcast -f /home/shoutcast/sc_serv
    + '[' '((' 0 = 0 ')' -a '(' -z '' -a 1 -eq 0 ')' -o '(' -z '' -a 1 -eq 1 '))' -o '((' 0 = 1 ')' -a '(' '!' -e /home/shoutcast/server.pid '))' ']'
    ./shoutcast-control: line 55: [: too many arguments
    + echo -ne '\033[0;31mERROR\033[0m Server scheint bereits online zu sein...\n'
    ERROR Server scheint bereits online zu sein...
    + exit 1
    Kann das sein, dass er bei so einer geringen Anzahl an Anweisungen schon schlapp macht?

    Die If-Anweisung dazu:
    Code:
    if [ \(\( $use_pid = 0 \) -a \( -z "`pgrep -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 0 \) -o \( -z "`pgrep -u $username -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 1 \)\) -o \(\( $use_pid = 1 \) -a \( ! -e "${path_shoutcast}/server.pid" \)\) ]; then
    MfG
    Michael
    Geändert von Fireball22 (06-02-2008 um 00:37 Uhr)

  14. #74
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Fireball22 Beitrag anzeigen
    ...Die If-Anweisung dazu:
    Code:
    if [ \(\( $use_pid = 0 \) -a \( -z "`pgrep -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 0 \) -o \( -z "`pgrep -u $username -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 1 \)\) -o \(\( $use_pid = 1 \) -a \( ! -e "${path_shoutcast}/server.pid" \)\) ]; then
    Geschachtelte Klammern in einer test-Anweisung müssen mit einem Leerzeichen getrennt werden:
    Code:
     if [ \( \( $use_pid = 0 \) -a \( -z "`pgrep -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 0 \) -o \( -z "`pgrep -u $username -f \"${path_shoutcast}/sc_serv\"`" -a $use_user -eq 1 \) \) -o \( \( $use_pid = 1 \) -a \( ! -e "${path_shoutcast}/server.pid" \) \) ]; then
    Nur so können sie als separate Argumente des test erkannt werden.

    Jan

    P.S.: Du fragst für den stop immer noch den Parameter $use_user ab - DAS BRINGT NICHTS! Das habe ich jetzt schon etliche Male zu erklären versucht - Du weisst nicht, mit welchen Parametern der sc_serv gestartet wurde! Er kann mit einem beliebigen User laufen, völlig unabhängig davon, wie Du das stop-Script aufrufst. Du kriegst ihn nicht gestoppt (bzw. erkennst nicht mal, das da überhaupt noch einer läuft), wenn Du weiter mit dieser unsinnigen Abfrage rumhantierst. Das Gleiche gilt für den Start: Du kriegst keinen neuen sc_serv gestartet, wenn da noch einer läuft (es ist schnurzpiepegal, von wem der gestartet wurde).

    Bau Dir doch mal eine Testumgebung, wo Du das prüfen kannst: Kopier Dir das Start-Script, setze einmal use_user auf 0 und einmal auf 1, starte beide Varianten (unter einem User, der NICHT $username ist) und schau Dir dann mal an, wie der start / stop abläuft (beide Scriptvarianten abwechselnd in unterschiedlicher Reihenfolge aufrufen).

    P.P.S.: Ich wiederhole auch das nochmal - [ -e datei ] testet nur die Existenz der Datei - das kann ein Verzeichnis, eine Named Pipe oder ein Device sein und Du brauchst keine Leseberechtigung auf das Ding - das nützt Dir überhaupt nix! Wenn Du ein PID-File auswerten willst, muss es eine reguläre Datei sein und Du musst sie lesen können. Nimm -f und -r stattdessen. Und wenn Du sie löschen / neu anlegen willst, dann brauchst Du Schreibberechtigung im Verzeichnis.

  15. #75
    Registrierter Benutzer
    Registriert seit
    17.12.2007
    Beiträge
    40
    Vielen Dank nochmals für deine Hilfe!

    Jetzt klappt es auch mit der If-Anweisung! =)

    Zu den Tests für die PID-File:
    Eig. reicht aber -e vollkommen aus, da ich ja keine PIDs aus der Datei auslesen, sondern nur nachschaue ob dieses "Objekt" existiert.
    Mein Script schreibt nicht einmal irgendetwas in diese File, dieses ist eig. komplett leer und signalisiert nur den Status des Servers.

    Allerdings verstehe ich das leider immer noch nicht ganz wie du das meinst, dass mein Script das ganze dann nicht killen kann!

    Weil ich habe mir das ganze so vorgestellt, dass man den Server mit diesem Script startet, alle Variablen so belässt und daraufhin den Server mit diesem Script wieder stoppt.

    Ich bin gerademal (fast) alle möglichen Fälle durchgegangen:

    $use_user = 1
    START:
    Script wird beispielsweise unter Benutzer "tux" gestartet.
    Server läuft inkl. Screen unter der Benutzerebene "shoutcast".

    STOP:
    - Server wird inkl. Screen mit su -c und pkill -u Parametern gekillt, egal mit welchem User das Script aufgerufen wird, da er immer den User nimmt, der bereits in der Variable $username festgelegt wurde, da $use_use = 1.

    $use_use = 0
    START:
    1) Als Root
    2) Als "tux1"
    3) Als "tux2"

    STOP:
    1) pkill wird unter root ausgeführt: Ausreichende Rechte um alle Prozesse, die unter Root gestartet wurden zu killen
    2) pkill wird unter "tux1" ausgführt: Ausreichende Rechte um alle Prozesse, die unter "tux1" laufen zu killen
    3) Ebenfalls ausreichende Rechte wie bei Fall 2

    NUR wenn ich jetzt versuche, den Server in Fall2 zu starten und ihn dann in Fall3 stoppe, werde ich Probleme haben, da der Server (evtl. mit Screen) unter "tux1" läuft und "tux2" keine Rechte hat, diesen zu beenden und dieses das Script auch nicht vorsieht.
    Das Script würde mit einer Fehlermeldung abbrechen.
    Aber dafür ist das Script eig. auch gar nicht gedacht, denn für das Handling und das Starten/Stoppen MIT und UNTER unterschiedlichen Benutzern gibt es ja die Funktion $use_user.

    Und das ist auch so gedacht, denn es gibt aufjedenfall Möglichkeiten, mehrere SHOUTcast-Server auf einem Rechner laufen zu lassen, dazu gibt es ettliche Mods.
    Und daher möchte ich auch nicht alle "sc_serv"s von allen Benutzern killen, sondern echt nimmer nur explizit diesen Servern, der mit dem Script gestartet wurde.

    Das ist doch soweit richtig, oder?

    MfG
    Michael

    EDIT:

    Beim testen ist mir noch aufgefallen, dass er bei folgendem Code IMMER nach dem Passwort frägt, auch wenn man als $username eingeloggt ist, außer man ist Root.
    Code:
    su -c "screen -dmS sc1 '${path_shoutcast}/sc_serv'" $username
    Kann man dieses Problem irgendwie umgehen, oder helfen da nur extra Startanweisungen dazu?
    Geändert von Fireball22 (06-02-2008 um 14:34 Uhr)

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •