Funktion in sh script?

cat1510

Well-Known Member
Hallo Leutz, das ist mein Script...

Habe die Funktion fehler definert.
Kann ich aber nicht abrufen.
Wo ist der Fehler?

Code:
#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin

#############################

# Device angeben auf dass gedumpt wird.

DEV=/dev/mirror/gm0s1

############################

# Error Control

fehler() {
   if [ $? -ne 0 ]
        then
        echo "Es ist ein Fehler aufgetreten!"
        exit 1
   fi
 }

###########################

newfs -U ${DEV}a
fehler
echo $?
mounr ${DEV}a /mnt
fehler $?
error


exit


Ausgabe in der shell:

Code:
(ROOT@server)~# /etc/dump.sh                                                                (2007-01-09 12:46:05)
newfs: /dev/mirror/gm0s1a: could not find special device
0
mounr: not found
127
error: not found
( return=127 ROOT@server)~#
 

walt

Well-Known Member
Wenn Du den exit status zu einem bestimmten Befehl speichern
moechtest, solltest Du direkt nach der Ausfuehrung des bestimmten Befehls
den exit status einer Variablen zuweisen (a=$?) weil $? nach der
Ausfuehrung des naechsten Befehls einen neuen Wert annimmt.

Was mich nur wundert ist, dass Dein script bis zum Ende durchlaeuft.
Es sollte eigentlich schon beim zweiten Aufruf der Funktion fehler
durch exit 1 beendet werden. So verhaelt es sich jedenfalls bei mir.
 

0815Chaot

FreeBSD/sparc64-Tüftler
Wie walt bereits schrieb, wird $? vom nächsten Befehlsaufruf sofort überschrieben. Du solltest $? statt dessen immer als Argument an fehler() übergeben, wie du das beim zweiten Aufruf von fehler() auch getan hast. Innerhalb von fehler() greifst du dann per $1 auf das erste übergebene Argument zurück. Das sollte schließlich wie folgt aussehen:
Code:
#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin

#############################

# Device angeben[color=red],[/color] auf [color=red]das[/color] gedumpt wird.

DEV=/dev/mirror/gm0s1

############################

# Error Control

fehler() {
   if [ $[color=red]1[/color] -ne 0 ]
        then
        echo "Es ist ein Fehler aufgetreten!"
        exit 1
   fi
 }

###########################

newfs -U ${DEV}a
fehler [color=red]$?[/color]
echo $?
mounr ${DEV}a /mnt
fehler $?
error
 

MrFixit

aka uqs
Bitte
Code:
if [ "$1" -ne 0 ]
verwenden. Oder wer garantiert, dass fehler() immer mit Argument aufgerufen wird?

Ein Fehler in der fehler()-Funktion .... *schmunzel*
 

0815Chaot

FreeBSD/sparc64-Tüftler
Dann darf man allerdings nicht den numerischen Operator -ne verwenden, sondern benötigt dazu den String-Operator !=. Ein Fehler bei der Fehlerbehebung in der fehler()-Funktion. :D
 

cat1510

Well-Known Member
Habe nun erst Eure rege Anteilnahme gesehen.
Danke!

Habe inzwischen auch ein bisschen gelesen und getestet. Dabei ist mir was merkwuerdiges aufgefallen.
Unter Ubuntu, mit der gleichen zsh geht es mit meiner Idee einwandfrei.
Natruelich ist mir klar, dass das keine Rolle spielt, da es eh in der sh laeuft.
Das Script ist noch nicht an Eure Anmerkungen angepasst...

Code:
#!/bin/sh

set -x

error_func() 
{

        if [ $? -ne 0 ]
                then
                echo "Das ist ein Fehler!"
                exit
        fi
}

mounr
error_func


exit

Wenn ich das ausfuehr:
Code:
(cat@Ubuntu)~% ./test.sh                                                                    (2007-01-10 01:17:36)
+ mounr
./test.sh: 1: mounr: not found
+ error_func
+ [ 127 -ne 0 ]
+ echo Das ist ein Fehler!
Das ist ein Fehler!
+ exit

Unter BSD:

Code:
(ROOT@server)~# ./test.sh                                                                   (2007-01-10 01:16:02)
+ PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin
+ mounr
mounr: not found
+ error_func
+ [ 0 -ne 0 ]
+ exit

Warum ist das unter BSD kein 'Fehler', dass es den Befehl nicht gibt, wie bei Ubuntu?
*g Wo muss ich das denn in der Registry einstellen? ;o)

Muss ich denn $? in eine Variable schreiben, wenn ich direkt mit dem naechsten Befehl den Status abfrage?

MFG

CAT
 

0815Chaot

FreeBSD/sparc64-Tüftler
Du fragst den Status aber gar nicht mit dem nächsten Befehl ab, sondern dein nächster Befehl ist ja der Aufruf von fehler(). Erst in fehler() fragst du dann nach $?. Jetzt ist natürlich die Frage, was die jeweilige Shell beim Aufruf einer Funktion mit der Variablen $? anstellt. Bedenke dabei, daß /bin/sh unter FreeBSD eine Almquist-Shell und unter Linux eine Bourne-Again-Shell ist. Die zsh ist natürlich wieder eine komplett andere Shell. Es gibt da also keinen Schalter, den du einfach umlegen kannst, sondern es handelt sich hier einfach um ein inkompatibles Verhalten zwischen verschiedenen Shells.

Wenn du portabel programmieren willst, dann verwende nicht /bin/sh, sondern verlange ausdrücklich nach einer Shell, die auf allen relevanten Systemen tatsächlich die gleiche Funktionalität bietet (z.B. bash oder zsh). Wenn du dagegen /bin/sh verwendest, mußt du eben gerade solche Dinge wie oben bedenken.
 

cat1510

Well-Known Member
Aha!

Das ist doch mal eine erklaerung!
Danke!

Was mich natuerlich wundert, dass sh nicht gleich sh ist.
Aber ok.
Dann werd ich nun meine scripts einfach fuer zsh schreiben.


Danke Danke.



CAT
 

0815Chaot

FreeBSD/sparc64-Tüftler
Käse. sh ist die kommerzielle Bourne-Shell. FreeBSD und NetBSD verwenden daher als /bin/sh die erwähnte Almquist-Shell, OpenBSD die Public-Domain-Korn-Shell, Solaris die Korn-Shell und Linux die Bourne-Again-Shell. Gegenteilige Behauptungen sind falsch, halten sich aber nach wie vor äußerst hartnäckig.

Der Wikipedia-Artikel zur Bourne-Shell ist in dieser Hinsicht zwar unvollständig, sollte aber einigermaßen verständlich machen, wo das Problem bei der ganzen Sache liegt.

Als Test kann man etwa mal folgendes Skript ausprobieren:
Code:
#!/bin/sh
declare -i INTEGER
Unter Linux läuft das. Unter FreeBSD heißt es nur "declare: not found", denn es handelt sich dabei um ein bash-spezifisches Feature.
 

0815Chaot

FreeBSD/sparc64-Tüftler
Nein! Warum überzeugst du dich eigentlich nicht erst von dem, was du da schreibst, statt mit irgendwelchen Vermutungen um dich zu werfen?
Code:
> test "0" -ne 0   # $? = 1
> test "42" -ne 0  # $? = 0
> test "" -ne 0
test: : bad number
> test "" != 0     # $? = 0
Das heißt, gerade in dem Fall, auf den sich dein Einwand bezog, nämlich daß fehler() kein Argument übergeben wird und $1 somit leer ist, fällt -ne auf die Nase.

Vielleicht solltest du dir nochmal überlegen, wie test(1) eigentlich die Typumwandlungen vornimmt. Guck im Zweifel halt in den Source.
 

MrFixit

aka uqs
Wir haben aneinander vorbeigeredet. Mea culpa. Ich ging im zweiten Fall von gesetztem $1 aus. (Und solche Annahmen sind beim Programmieren immer schlecht)
 
Oben