Bio: (BASH) Kommandos mit Ausgabe schlagen in Skript fehl

Sup!

Ich habe ein Problem. In einem Skript (usb.agent, für USB-Hotplugging), das vom Kernel-Hotplug-Dämon angestossen wird, habe ich einen Fehler entdeckt; dort steht irgendwo

if ! lsmod | grep -q "^$MODULE"; then
...
fi

Das ergibt aber immer "true" (als würde das Modul nie geladen sein), und der Inhalt des ifs wird immer ausgeführt.

Das anscheinend deshalb, weil unter GNU/Linux (in der Man-Page von grep wird auch davor gewarnt!) grep -q wohl nicht wirklich ganz auf eine Ausgabe verzichtet, was anscheinend den Fehler auslöst.

Als Test habe ich folgendes ins Skript geschrieben:

echo "bla bla" | grep "bla" >/dev/null 2>&1
logger ${PIPESTATUS[*]}
echo "bla bla" | grep -q "bla"
logger ${PIPESTATUS[*]}

(Die Bash stellt netterweise die Exit-Stati aller Kommandos in einer Pipe im Array PIPESTATUS zur Verfügung)

Ersteres Kommand ergibt im Log 0 0 (beide Kommandos erfolgreich), zweiteres 0 2 (echo klappt, aber grep versagt mit System-Fehler)

Wie kann das sein? Ist in System-Skripten STDOUT immer geschlossen?

Gruesse,

Bio

--
Keep your friends close, but STDOUT open!
  1. 你好 Bio,

    Wie kann das sein? Ist in System-Skripten STDOUT immer geschlossen?

    Immer nicht, nein -- aber moeglich ist das durchaus.

    再见,
    克里斯蒂安

    --
    Keine Schneeflocke faellt je auf die falsche Stelle.
  2. Hi,

    Ich habe ein Problem. In einem Skript (usb.agent, für USB-Hotplugging), das vom Kernel-Hotplug-Dämon angestossen wird, habe ich einen Fehler entdeckt; dort steht irgendwo

    if ! lsmod | grep -q "^$MODULE"; then
    ...
    fi

    Das ergibt aber immer "true" (als würde das Modul nie geladen sein), und der Inhalt des ifs wird immer ausgeführt.

    Das kann durchaus korrekt sein. Ist das Modul wirklich vor Ausführung des Script(teil)es nicht geladen? Ist $MODULE gefüllt? Nutze z.B. 'logger' oder 'echo' um das herauszubekommen.

    Als Test habe ich folgendes ins Skript geschrieben:

    echo "bla bla" | grep "bla" >/dev/null 2>&1
    logger ${PIPESTATUS[*]}
    echo "bla bla" | grep -q "bla"
    logger ${PIPESTATUS[*]}

    Ersteres Kommand ergibt im Log 0 0 (beide Kommandos erfolgreich), zweiteres 0 2 (echo klappt, aber grep versagt mit System-Fehler)

    Laut den <http://linuxreviews.org/beginner/abs-guide/en/a16609.html@titleBash Exitcodes> deutet es darauf hin, das dsa benutze grep ein Shellbuiltin ist(?). Suche einmal nach bin/grep und gebe den so gefundenen Pfad ein. Es ist sowieso eine Unsitte sich in Scripten darauf zu verlassen, das das richtige Programm in $PATH ist _und_ auch wirklich das Programm und kein Shellbultin.

    Wie kann das sein? Ist in System-Skripten STDOUT immer geschlossen?

    Welches STDOUT meinst Du? bei jeder Programmausführung werden per Default drei Dateien geöffnet STDERR, STDIN und STDOUT. Die kann da Programm zwar wieder schließen, aber dazu gibt es gewöhnlich keinen Grund. Anders sieht das natürlich mit Shellbuiltins aus. Da pro Programm nur je _einmal_ diese drei Dateien geöffnet werden, funktioniert das bei den Pipes dann etwas anders.

    Nichtsdestotrotz: das scheint mir eine Aneinanderreihung von Unsauberkeiten zu sein, die hier einen Bug ergeben.

    Aber ich würde mir da keinen Kopf machen, sondern einfach obige Vorschläge einmal durchprobieren und wenn es immer noch nicht klappt das ganze Script hier verlinken, dann steckt der Fehler höchstwahrscheinlich in einem anderem Detail.

    so short

    Christoph Zurnieden

    1. Sup!

      if ! lsmod | grep -q "^$MODULE"; then
      ...
      fi

      Das ergibt aber immer "true" (als würde das Modul nie geladen sein), und der Inhalt des ifs wird immer ausgeführt.

      Das kann durchaus korrekt sein. Ist das Modul wirklich vor Ausführung des Script(teil)es nicht geladen? Ist $MODULE gefüllt? Nutze z.B. 'logger' oder 'echo' um das herauszubekommen.

      Das Modul ist geladen und die Variable gesetzt, und wie hier:

      Als Test habe ich folgendes ins Skript geschrieben:

      echo "bla bla" | grep "bla" >/dev/null 2>&1
      logger ${PIPESTATUS[*]}
      echo "bla bla" | grep -q "bla"
      logger ${PIPESTATUS[*]}

      zu sehen kenne ich "logger" ;-)

      Ersteres Kommand ergibt im Log 0 0 (beide Kommandos erfolgreich), zweiteres 0 2 (echo klappt, aber grep versagt mit System-Fehler)

      Laut den <http://linuxreviews.org/beginner/abs-guide/en/a16609.html@titleBash Exitcodes> deutet es darauf hin, das dsa benutze grep ein Shellbuiltin ist(?).

      Ne, ist es nicht. Nicht nur Shell-Builtins können einen Fehlercode 2 werfen.

      Suche einmal nach bin/grep und gebe den so gefundenen Pfad ein. Es ist sowieso eine Unsitte sich in Scripten darauf zu verlassen, das das richtige Programm in $PATH ist _und_ auch wirklich das Programm und kein Shellbultin.

      PATH ist richtig gesetzt und die Bash hat wirklich kein eingebautes grep.

      Welches STDOUT meinst Du? bei jeder Programmausführung werden per Default drei Dateien geöffnet STDERR, STDIN und STDOUT. Die kann da Programm zwar wieder schließen, aber dazu gibt es gewöhnlich keinen Grund. Anders sieht das natürlich mit Shellbuiltins aus. Da pro Programm nur je _einmal_ diese drei Dateien geöffnet werden, funktioniert das bei den Pipes dann etwas anders.

      Es kann nur ein STDOUT geben! ;-)
      Es scheint tatsächlich so, als ob in manchen System-Skripten STDOUT geschlossen ist, man also Probleme bekommt, wenn man z.B. "echo" benutzt (weil es fehlschlägt) oder Kommandos, die Ausgaben machen und so gut programmiert sind, beim Fehlschlagen der Ausgabe mit Fehlercode abzubrechen.

      Nichtsdestotrotz: das scheint mir eine Aneinanderreihung von Unsauberkeiten zu sein, die hier einen Bug ergeben.

      Nein, es scheint so, als wäre allein die Ausgabe der Fehlergrund.
      In der neuesten CVS-Version der hotplug-Skripte hat man jedenfalls genau diese Zeile ebenfalls mit >/dev/null 2>&1 versehen.

      Gruesse,

      Bio

      --
      Keep your friends close, but your enemies closer!
      1. Hi,

        ich muß zuerst etwas gestehen: ich hab' Dich mit jemandem verwechselt und deshalb alles etwas ... äh ... einfacher formuliert. Bitte höflichst um Entshuldigung.

        logger ${PIPESTATUS[*]}

        zu sehen kenne ich "logger" ;-)

        Nun, das kann auch C&P aus der großen Bash-Anleitung sein ;-)

        Laut den <http://linuxreviews.org/beginner/abs-guide/en/a16609.html@titleBash Exitcodes> deutet es darauf hin, das dsa benutze grep ein Shellbuiltin ist(?).

        Ne, ist es nicht. Nicht nur Shell-Builtins können einen Fehlercode 2 werfen.

        Drum auch das Fragezeichen, hätte mich auch gewundert, aber ich bin nicht überall auf dem neuestem Stand, insbesondere bei so grundlegenden Programmen wie der Shell.

        Es kann nur ein STDOUT geben! ;-)

        Es gibt nur eine Datei, aber jedes Programm -- dazu gehören natürlich auch die Subshells -- macht seinen eigenen Filepointer drauf auf.

        Nichtsdestotrotz: das scheint mir eine Aneinanderreihung von Unsauberkeiten zu sein, die hier einen Bug ergeben.

        Nein, es scheint so, als wäre allein die Ausgabe der Fehlergrund.

        Das darf kein Fehlergrund sein, das ist eifach ein Bug. Da brauchen sich die verantworlichen Programmierer gar nicht erst rauszureden, sowas gehört abgefangen!
        'dammtnochmal!
        ;-)

        In der neuesten CVS-Version der hotplug-Skripte hat man jedenfalls genau diese Zeile ebenfalls mit >/dev/null 2>&1 versehen.

        Ja, das sieht doch schon besser aus, ist aber im Grunde nur ein Workaround.

        Da ich das aber auf meiner Kiste nicht nachvollziehen kann, ich aber jetzt blöderweise neugierig geworden bin,  wäre ich an den einzelnen Versionen interessiert. Zum bequemem C&P (sensible Informationen bitte kürzen oder ganz entfernen!):
        echo -n sh = which sh Version =; echo $(which sh --version);echo -n bash = which bash Version =; echo $(which bash --version);echo -n grep = which grep Version =; echo $(which grep --version);echo -n gcc = which gcc Version =; echo $(which gcc --version);echo "";uname -r;echo "libc:"; /lib/libc.so.6 --version

        so short

        Christoph Zurnieden