Shell Script Fehler

Daroo

Member
Guten Tag Liebe BSDForen User,
ich habe ein Problem mit einem Shellscript, welches ich aus
Übungszwecken und der Vereinfachung willen geschrieben habe:
PHP:
#!/bin/sh
#System Installer by
###############################################
###############################################
###	#####	######	#####	######	######	###
###	##	##	##	##	##	##	##	##	##	##	###
###	##	##	######	##	##	##	##	##	##	###
###	##	##	##	##	#####	##	##	##	##	###
###	#####	##	##	##	##	######	######	###
###						##					###
###############################################
###############################################
##-------------------------------------------##
##Variablen
RELEASE=$(uname -r)
FETCHSERVER="http://example.com/$RELEASE"
SSYS="/usr/src/sys/conf"
TESTFILE="test.tar.gz"
SRCFILE="ssys.tar.gz"
SRCDIR="/usr/src/"
K1="IPFW"
K2="PAE"
K3="PF"
K4="Daroonator"
FWRULES="firewall.rules"
PFRULES="pf.conf"
RC="/etc/rc.conf"
CURDIR="./"
MYSQLUSR="mysql.tar.gz"
MYSQL="/var/db/mysql"
PORTSUPDATE=0
PORTS="/usr/ports"
SQUID="squid.conf"
##Connection Test
while [ "$SERVERCON" != "end" ]
do
    if [ "$CONNUM" == 2 ]; then
        FETCHSERVER=http://example2.com/$RELEASE
        fetch $FETCHSERVER/$TESTFILE
        clear
        if test ! -f $TESTFILE
		then
            echo -e "\033[31m \n Server nicht erreichbar!\033[0m"
            sleep 3
			clear
			exit
        else
            clear
			rm $TESTFILE
            SERVERCON=end
        fi
    else
        fetch $FETCHSERVER/$TESTFILE
        clear
        if test ! -f "$TESTFILE"
		then
            CONNUM = 'expr $CONNUM + 1'
        else
            clear
			rm $TESTFILE
            SERVERCON=end
        fi
    fi
done
if [ $SERVERCON == "end" ]; then
##Funktionen
#IPFW
if [ $1 == 1 ]; then
	echo -e "\033[31mÜberprüfe Sources...\033[0m"
	if test ! -d $SSYS
	then
		echo -e "\033[31mDownload Sources...\033[0m"
		fetch $FETCHSERVER/$SRCFILE
		tar zxf $SRCFILE -C $SRCDIR
		echo -e "\033[31mSources erfolgreich installiert!\033[0m"
		rehash
	fi
	echo -e "\033[31mInstalliere IP-Firewall...\033[0m"
	make buildkernel KERNCONF=$K1
	make installkernel KERNCONF=$K1
	echo -e "\033[31mIP-Firewall-Installation abgeschlossen!\033[0m"
	fetch $FETCHSERVER/$FWRULES
	mv $PFRULES /etc/$FWRULES
	echo 'firewall_enable="YES"' >> $RC
	echo 'firewall_script="/etc/firewall.rules"' >> $RC
	sleep 10
	clear
	sh install.sh F
##PAE
elif [ $1 == 2 ]; then
	echo -e "\033[31mÜberprüfe Sources...\033[0m"
	if test ! -d $SSYS
	then
		echo -e "\033[31mDownload Sources...\033[0m"
		fetch $FETCHSERVER/$SRCFILE
		tar zxf $SRCFILE -C $SRCDIR
		echo -e "\033[31mSources erfolgreich installiert!\033[0m"
		rehash
	fi
	echo -e "\033[31mInstalliere PAE...\033[0m"
	make buildkernel KERNCONF=$K2
	make installkernel KERNCONF=$K2
	echo -e "\033[31mPAE-Installation abgeschlossen!\033[0m"
	sleep 10
	clear
	sh install.sh F
##PF
elif [ $1 == 3 ]; then
	echo -e "\033[31mÜberprüfe Sources...\033[0m"
	if test ! -d $SSYS
	then
		echo -e "\033[31mDownload Sources...\033[0m"
		fetch $FETCHSERVER/$SRCFILE
		tar zxf $SRCFILE -C $SRCDIR
		echo -e "\033[31mSources erfolgreich installiert!\033[0m"
		rehash
	fi
	echo -e "\033[31mInstalliere Paketfilter...\033[0m"
	make buildkernel KERNCONF=$K3
	make installkernel KERNCONF=$K3
	echo -e "\033[31mPaketfilter-Installation abgeschlossen!\033[0m"
	fetch $FETCHSERVER/$PFRULES
	mv $PFRULES /etc/$PFRULES
	echo 'pf_enable="YES"' >> $RC
	echo 'pf_rules="/etc/pf.conf"' >> $RC
	sleep 10
	clear
	sh install.sh F
##Daroonator
elif [ $1 == 4 ]; then
	echo -e "\033[31mÜberprüfe Sources...\033[0m"
	if test ! -d $SSYS
	then
		echo -e "\033[31mDownload Sources...\033[0m"
		fetch $FETCHSERVER/$SRCFILE
		tar zxf $SRCFILE -C $SRCDIR
		echo -e "\033[31mSources erfolgreich installiert!\033[0m"
		rehash
	fi
	echo -e "\033[31mInstalliere Daroonator-Kernel...\033[0m"
	make buildkernel KERNCONF=$K4
	make installkernel KERNCONF=$K4
	echo -e "\033[31mDaroonator-Installation abgeschlossen!\033[0m"
	fetch $FETCHSERVER/$PFRULES
	mv $PFRULES /etc/$PFRULES
	echo 'pf_enable="YES"' >> $RC
	echo 'pf_rules="/etc/pf.conf"' >> $RC
	fetch $FETCHSERVER/$FWRULES
	mv $PFRULES /etc/$FWRULES
	echo 'firewall_enable="YES"' >> $RC
	echo 'firewall_script="/etc/firewall.rules"' >> $RC
	sleep 10
	clear
	sh install.sh F
##TestFunktion
elif [ $1 == 5 ]; then
	echo "Funktion zur Zeit nicht bereit!"
	sleep 10
	clear
	sh install.sh F
##MySQL
elif [ $1 == 6 ]; then
	echo -e "\033[31mÜberprüfe Ports...\033[0m"
	if test ! -d "$PORTS"
	then
		echo -e "\033[31mInstalliere Ports...\033[0m"
		portsnap fetch extract
	fi
	if [ $PORTSUPDATE != 1 ]; then
		echo -e "\033[31mUpdate Ports...\033[0m"
		portsnap fetch update
		PORTSUPDATE=1
	fi
	echo -e "\033[31mInstalliere MySQL 5.1...\033[0m"
	cd $PORTS/databases/mysql51-server
	make install WITH_XCHARSET=all
	make clean
	fetch $FETCHSERVER/$MYSQLUSR
	tar zxf $MYSQLUSER -C $MYSQL/mysql
	chown -R $MYSQL
	chgrp -R $MYSQL
	read PASSWORD
	/usr/local/bin/mysqladmin -u root password $PASSWORD
	cd $CURDIR
	rehash
	echo -e "\033[31mMySQL 5.1-Installation abgeschlossen\033[0m"
	sleep 10
	clear
	sh install.sh F
##Screen
elif [ $1 == 7 ]; then
	echo -e "\033[31mÜberprüfe Ports...\033[0m"
	if test ! -d "$PORTS"
	then
		echo -e "\033[31mInstalliere Ports...\033[0m"
		portsnap fetch extract
	fi
	if [ $PORTSUPDATE != 1 ]; then
		echo -e "\033[31mUpdate Ports...\033[0m"
		portsnap fetch update
		PORTSUPDATE=1
	fi
	echo -e "\033[31mInstalliere Screen...\033[0m"
	cd $PORTS/sysutils/screen
	make -DBTACH install
	make clean
	rehash
	cd $CURDIR
	echo -e "\033[31mScreen-Installation abgeschlossen!\033[0m"
	sleep 10
	clear
	sh install.sh F
##Squid
elif [ $1 == 8 ]; then
	echo -e "\033[31mÜberprüfe Ports...\033[0m"
	if test ! -d "$PORTS"
	then
		echo -e "\033[31mInstalliere Ports...\033[0m"
		portsnap fetch extract
	fi
	if [ $PORTSUPDATE != 1 ];then
		echo -e "\033[31mUpdate Ports...\033[0m"
		portsnap fetch update
		PORTSUPDATE=1
	fi
	echo -e "\033[31mInstalliere Squid...\033[0m"
	cd $PORTS/www/squid
	make -DBATCH install
	make clean
	/usr/local/sbin/squid -z
	cd /usr/local/etc/
	rm squid.conf
	fetch $fetchserver/$SQUID
	echo 'squid_enable="YES"' >> $RC
	rehash
	cd $CURDIR
	echo -e "\033[31mSquid Installation abgeschlossen!\033[0m"
	sleep 10
	clear
	sh install.sh F
##Sudo
elif [ $1 == 9 ]; then
	echo -e "\033[31mÜberprüfe Ports...\033[0m"
	if test ! -d "$PORTS"
	then
		echo -e "\033[31mInstalliere Ports...\033[0m"
		portsnap fetch extract
	fi
	if [ $PORTSUPDATE != 1 ]; then
		echo -e "\033[31mUpdate Ports...\033[0m"
		portsnap fetch update
		PORTSUPDATE=1
	fi
	echo -e "\033[31mInstalliere Sudo...\033[0m"
	cd $PORTS/security/sudo
	make -DBATCH install
	make clean
	rehash
	cd $CURDIR
	echo -e "\033[31mSudo-Installation abgeschlossen!\033[0m"
	sleep 10
	clear
	sh install.sh F
##Python
elif [ $1 == 10 ]; then
	echo -e "\033[31mÜberprüfe Ports...\033[0m"
	if test ! -d "$PORTS"
	then
		echo -e "\033[31mInstalliere Ports...\033[0m"
		portsnap fetch extract
	fi
	if [ $PORTSUPDATE != 1 ]; then
		echo -e "\033[31mUpdate Ports...\033[0m"
		portsnap fetch update
		PORTSUPDATE=1
	fi
	echo -e "\033[31mInstalliere Python...\033[0m"
	cd $PORTS/lang/python
	make -DBATCH install
	make clean
	rehash
	cd $CURDIR
	echo -e "\033[31mPython-Installation abgeschlossen!\033[0m"
	sleep 10
	clear
	sh install.sh F
##Perl
elif [ $1 == 11 ]; then
	echo -e "\033[31mÜberprüfe Ports...\033[0m"
	if test ! -d "$PORTS"
	then
		echo -e "\033[31mInstalliere Ports...\033[0m"
		portsnap fetch extract
	fi
	if [ $PORTSUPDATE != 1 ];then
		echo -e "\033[31mUpdate Ports...\033[0m"
		portsnap fetch update
		PORTSUPDATE=1
	fi
	echo -e "\033[31mInstalliere Perl 5.8...\033[0m"
	cd $PORTS/lang/perl5.8
	make -DBATCH install
	make clean
	rehash
	cd $CURDIR
	echo -e "\033[31mPerl5.8-Installation abgeschlossen!\033[0m"
	sleep 10
	clear
	sh install.sh F
##Flood
elif [ $1 == 12 ]; then
	echo -e "\033[31mDownloade UDP-Flood Script...\033[0m"
	fetch $FETCHSERVER/$FLOOD
	echo -e "\033[31mBitte gebe die IP ein!\033[0m"
	read ip
	perl $FLOOD $IP
	rm $FLOOD
	sleep 3
	clear
	sh install.sh F
##Quit
elif [ $1 == [Qq] ]; then
	exit
##Nach beenden
elif [ $1 == "F" ]; then
	echo -e "\033[31mInstallation (f)ortsetzen oder (b)eenden?[y/n]\033[0m"
	read choice
	if [ $choice == [Ff] ]; then
		clear
		sh install.sh
	elif [ $choice == [Bb] ]; then
		sleep 1
		clear
		exit
	else
		echo -e "\033[31mUngültige Eingabe!\033[0m"
		clear
		sh install.sh F
	fi	
##Hauptmenu

else
	if [ $RELEASE == "7.4-RELEASE" ] || [ $RELEASE == "8.1-RELEASE" ]; then 
		echo -e "\033[31mWillkommen beim Systeminstaller von Daroo\033[0m"
		echo -e "\033[31mBitte wähle eine Option:\033[0m"
		echo -e "\033[31m Kernel Installation \n
				1*) IP-Firewall
				2*) PAE
				3*) Packetfilter
				4*) IPFW+PAE+PF
		5*) Testpunkt \n
		6*) MySQL 5.1 Installation \n
		7*) Screen \n
		8*) Squid \n
		9*) Sudo \n
		10*) Python \n
		11*) Perl \n
		12*) Flood Script \n
		13*) Ende\033[0m"
		read chs
		sleep 1
		if [ $chs -ge 14 ]; then
			echo -e "\033[31mUngültige Eingabe!\033[0m"
			sleep 2
			clear
			sh install.sh
		else
			clear
			sleep 1
			sh install.sh $chs
		fi
	else
		echo -e "\033[31mDas Release $RELEASE ist nicht unterstützt.\033[0m"
	fi
fi
fi

Beim Ausführen kommt folgende Fehler meldung:
Code:
2P22# sh install.sh
install.sh: 93: Syntax error: "elif" unexpected (expecting "then")
2P22#

Nun frage ich mich, wo liegt mein Fehler? Ich würde das ungerne in Bash schreiben,
will Shell lernen.

Mit freundlichen Grüßen,
Daroo
 
Ich sehe spontan nicht, was da mit elif schiefläuft (da in Zeile 93 keines steht), aber vielleicht ist sh schon wegen etwas vorher verwirrt. Ich zähle ein paar Sachen auf, die mir aufgefallen sind. Hoffentlich hilft dir das weiter.

Generell sollte ein Shellskript nach dem #! in Zeile zwei
Code:
set -e
haben, damit es abbricht, falls etwas schiefläuft, anstatt beliebig weiterzulaufen und womöglich Schaden anzurichten.

Code:
fetch $FETCHSERVER/$TESTFILE
clear
if test ! -f $TESTFILE
Teste den Rückgabewert von fetch (if ! fetch ...; then), denn die Übertragung könnte auf halbem Wege abbrechen (auch würde das set -e das Skript abbrechen, wenn der Rückgabewert nicht getestet wird).

Code:
if [ "$CONNUM" == 2 ]; then
== ist ein Bashismus, der mit FreeBSDs sh nicht funktioniert. Es muss = heißen (an diversen Stellen).

Code:
echo -e "\033[31m \n Server nicht erreichbar!\033[0m"
sleep 3
clear
exit
Nach einem Fehler solltest du einen Wert != 0 zurückgeben. exit ohne Argument gibt den Rückgabewert des letzten Befehls zurück, was bei clear höchstwahrscheinlich 0 ist.
Auch erscheint es mir ungeschickt, die Fehlermeldung nach 3 Sekunden verschwinden zu lassen.

Code:
while [ "$SERVERCON" != "end" ]
do
...
SERVERCON=end
...
done
Verwende break, das ist einfacher:
Code:
while :; do
...
break
...
done

Code:
if [ $SERVERCON == "end" ]; then
Ich denke, der Test ist nach der Schleife redundant (und wieder ==).

Code:
CONNUM = 'expr $CONNUM + 1'
Das tätigt nicht die gewünschte Rechnung, sonden weißt einfach den Text (ohne die Variable auszulesen) CONNUM zu, denn das sind einfache Anführungszeichen ('...') statt Backticks (`...`).
Ich bemerke gerade, dass es nicht einmal das tut, denn da ist ein Leerzeichen vor dem =. Damit würde sh versuchen, ein Programm namens CONNUM zu starten. Bei Variablenzuweisungen darf kein Leerzeichen vor und hinter dem = sein.
Zudem sollte man expr meiden und stattdessen Arithmetik von sh verwenden:
Code:
CONNUM=$(($CONNUM + 1))

Code:
if test ! -d $SSYS
Anführungszeichen ("$SSYS") um Variablenverwendungen, denn falls der Wert Leerzeichen enthält bekommst du sonst mehrere Wörter statt eines.

Code:
rehash
Diesen Befehl kennt sh nicht (und hätte auch keinen Effekt auf die aufrufende Shell).

Code:
elif [ $1 == [Qq] ]; then
Das testet, ob $1 gleich "[Qq]" ist, nicht ob es entweder ein großes Q oder ein kleines q ist. (Zudem wieder = statt ==)


Code:
echo -e "\033[31m Kernel Installation \n
                1*) IP-Firewall
                ..."
Das \n (und asd -e) sind unnötig. Der Zeilenumbruch selbst wird schon als solcher ausgegeben. Aktuell wird so nach jeder Zeile eine Leerzeile ausgeben.
 
Mal ein paar Anmerkungen.

@Tron
Man kann auch einfach in die erste Zeile
#!/bin/sh -e
schreiben statt 'set -e' auszuführen. Mit -e zu arbeiten ist aber extrem ungemütlich, mache ich nie.

@Daroo
CONNUM=$((CONNUM + 1))
funktioniert auch und spart mal mindestens 2 Kontext Switches.

@Tron
Ohne das -e werden die Escapes (in dem Fall Farben) nicht interpretiert.
 
Mal ein paar Anmerkungen.

@Tron
Man kann auch einfach in die erste Zeile
#!/bin/sh -e
schreiben statt 'set -e' auszuführen. Mit -e zu arbeiten ist aber extrem ungemütlich, mache ich nie.
Schon selbst erlebt:
Code:
%./skript
cd: can't cd to qwe
%
und danach war ich in einem leeren Verzeichnis.
In dem Skript stand (mit Betonung auf die Verganheitsform!) u.a. folgendes:
Code:
cd qwe
rm -fr *
Bonuspunkte, wenn man das in $HOME ausführt. Das hat den Skriptautor davon überzeugt, dass set -e keine so schlechte Idee ist (von anderen Problemen mit den paar Zeilen mal ganz abgesehen).
Wenn etwas schief läuft, man ignoriert das und macht fröhlich weiter -- das kann langfristig nur explodieren.
set -e ist natürlich kein Allheilmittel, aber doch zumindest ein gewisses Sicherheitsnetz.
Daher halte ich das diametral: Ich schreibe nie ein Shellskript ohne -e.

@Tron
Ohne das -e werden die Escapes (in dem Fall Farben) nicht interpretiert.
echo -e ist natürlich auch ein Bashismus, was der Autor ja vermeiden will (leider unterstützt FreeBSDs sh den Mist). statt \033 sollte man direkt ein Escape-Zeichen verwenden: STRG+V ESC oder STRG+V STRG+[.
 
Hättest du mal

rm -rf qwe/*

geschrieben.


Glob Patterns für Dateinamen in Skripten sind schon ziemlich gehackt. Ich verwende normalerweise -f.
 
Im Gegensatz zu meinen Vorrednern, kenne ich mich nicht aus mit dieser Problematik, sehe mir aber gelegentlich mal Scripts anderer an und habe auch ganz einfache Dinge für eigene kleine Aufgaben schon selbst fabriziert.
Einen Fehler in deinem Script kann ich dir auch nicht nennen.
Das liegt vielleicht aber zum Teil an der Gestalltung.
Die if - then - else/elif fi Konstrukte werden ja immer von innen nach außen aufgelöst. Dabei ist es umso schwieriger zu sehen, ob die jeweilige "Klammerung" auch passt, desto mehr solche Konstrukte inneinander verschachtelt sind. Das kann für unbedarfte Außenstehende mitunter gar nicht recht durchblickt werden.
Dabei stellst du den ersten then meist in die Zeile, die auch die Entscheidung aufruft. Deshalb hatte ich das zunächst an manchen Stellen übersehen, denn du machst das nicht immer gleich. Wenn du übersichtlicher gliederst, findest du die "Umklammerung" einfacher und siehst vielleicht sofort, was da vielleicht fehlt. Vor allem, wenn du immer gleiche Syntax verwendest, kann das hilfreich sein.

Meiner Ansicht nach bleibt eine "Entscheidungsreihe" (du siehst, ich kenne mich nicht mal mit den gebräuchlichen Ausdrücken aus und erfinde mir nun Worte, die meiner Ansicht nach beschreiben, was ich meine), wie du sie mit den vielen if... elif durchläufst einfacher und übersichtlicher mit case.
Aber das mag Geschmacksache sein und vielleicht habe ich auch was nicht richtig verstanden in deinem Script.
 
Was, glaube ich, noch nicht gesagt wurde, in den if [] Tests die Kommandozeilenparameter $1 usw. immer in Anführungszeichen setzen, da du ja nicht garantieren kannst, dass das Skript mit allen Parametern aufgerufen wird.
 
und danach war ich in einem leeren Verzeichnis.
Weil's gerade so schön ist: Ein Kollege wollte einige überflüssige Backupfiles löschen und tippte
Code:
$ rm * .bck
rm: cannot remove `.bck': No such file or directory
Ich hätte zu gerne das Gesicht gesehen in den zwei, drei Sekunden, die er über diese rätselhafte Fehlermeldung grübelte.

echo -e ist natürlich auch ein Bashismus, was der Autor ja vermeiden will (leider unterstützt FreeBSDs sh den Mist). statt \033 sollte man direkt ein Escape-Zeichen verwenden
Im Prinzip hast Du zwar recht, aber ein nacktes ESC im Text bringt manchen Editor in Verwirrung. Besser folgt man der POSIX-Empfehlung und verzichtet ganz auf »echo« zugunsten von »printf«.

Deinem Hinweis zu »expr« muß ich aber widersprechen, denn die Bourne-Shell hat i. a. keine eingebaute Arithmetik in der Art »$(( ))«.

Insgesamt waren das aber ein paar coole Ratschläge von jemandem, der sich mit den Feinheiten auskennt. Danke!
 
Weil's gerade so schön ist: Ein Kollege wollte einige überflüssige Backupfiles löschen und tippte
Code:
$ rm * .bck
rm: cannot remove `.bck': No such file or directory
Ich hätte zu gerne das Gesicht gesehen in den zwei, drei Sekunden, die er über diese rätselhafte Fehlermeldung grübelte.
Ein echter Klassiker! (:

Im Prinzip hast Du zwar recht, aber ein nacktes ESC im Text bringt manchen Editor in Verwirrung. Besser folgt man der POSIX-Empfehlung und verzichtet ganz auf »echo« zugunsten von »printf«.
Dann ist der Editor Mist. Alle relevanten Editoren (d.h. vi) und Betriebssysteme (d.h. emacs) haben damit keine Probleme. (:<

Deinem Hinweis zu »expr« muß ich aber widersprechen, denn die Bourne-Shell hat i. a. keine eingebaute Arithmetik in der Art »$(( ))«.

Aus dem Kapitel Shell Command Language der SUSv2:
Arithmetic Expansion

Arithmetic expansion provides a mechanism for evaluating an arithmetic expression and substituting its value. The format for arithmetic expansion is as follows:

$((expression))
 
Vielen Dank für eure ganzen Verbesserungsvorschläge; könnte
mir vielleicht einer einen Abschnitt verbessert vorlegen, damit ich verstehen
kann, was ihr meint?
 
Code:
case $XXXSCHLEIFE in
            -v)
                echo "steak, version $VERSIONNUMMER: the dictionary for Unix (razi@cs.uni-frankfurt.de)"
                terminat_funktion
                ;;
            -h)
                #clear
                echo
                echo "steak, version $VERSIONNUMMER: the dictionary for Unix (razi@cs.uni-frankfurt.de)"
                echo
                cat $HELPFILE
                terminat_funktion
                ;;
            -noignor)
                IGNORVAR="N"
                ;;
            -and)
                ANDORVAR="1"
                ISPELLVAR="N"
                ;;
            -or)
                ANDORVAR="2"
                ISPELLVAR="N"
                ;;
            -e)
                CONFIGVAR="ENGLISCH->DEUTSCH"

                ;;
            -d)
                CONFIGVAR="DEUTSCH->ENGLISCH"
                ;;
            -de|-ed)
                CONFIGVAR="ENGLISCH<->DEUTSCH"
                ;;
            -nowait)
                POLLVAR="N"
                WAITVAR="N"
                SLEEPTIME=0
                ISPELLVAR="N"
                ;;
            -noispell)
                ISPELLVAR="N"
                ;;
            -k)
                POLLVAR="N"
                KONTEXTAUSGABEVAR="N"
                ;;
            +k)
                POLLVAR="N"
                KONTEXTAUSGABEVAR="J"
                ;;
            -clipboard)
                CLIPBOARDVAR="J"
                XXX=`$BUFFERPROGRAMM | sed -f $BINDIR/iso2txt`
                XXXUMLAUT=`$BUFFERPROGRAMM`
                ;;
            *)
                if [ $CLIPBOARDVAR = "N" ]
                then
                    XXX=`echo "$XXXSCHLEIFE" | sed -f $BINDIR/iso2txt`
                    XXXUMLAUT=`echo "$XXXSCHLEIFE"`
                fi
esac
Was meinen Einwand anbelangt, mache ich das gerne, aber das wird vermutlich das bleiben, was dir am wenigsten nutzen kann.
Nungut, das Beispiel oben ist aus einem Script, das ich mir unlängst angesehen hatte und es vermittelt eine Idee davon, wieso ich denke, dass mit case anstatt mit vielen elif die Sache übersichtlicher wird.
Aus dem gleichen Script zitiere ich mal noch zwei Entscheidungen:
Code:
if [ $# -eq 0 ]
if [ "$BUFFERPROGRAMM" = "xcb -p 0" ]
Also "=" oder "-eq" statt "==" und wenigstens im letzten Beispiel, Variablen-Werte in "".
Ein Beispiel dafür, wie die "Klammerung" einer if - then -else - fi Konstruktion deutlicher wird, kann der letzte Ausdruck aus Beispiel eins gelten. Das hätte auch alles in eine einzige Zeile gequetscht werden können, etwa:
Code:
[ $CLIPBOARDVAR = "N" ] && XXX=`echo "$XXXSCHLEIFE" | sed -f $BINDIR/iso2txt` && XXXUMLAUT=`echo "$XXXSCHLEIFE"`
Wobei es mir nun nicht auf vollkommene Übereinstimmung zwischen beiden Möglichkeiten ankommt, sondern nur auf die unterschiedlichen Formen. Je nach Zweck kann mal das eine oder mal das Andere übersichtlicher sein und ich glaube, dass man sich die Sache einfacher macht, wenn man an strengen Formen festhält.
 
Na sowas! Ich habe ein wenig recherchiert: Offenbar beherrschen spätere Versionen der Bourne-Shell das schon, z. B. nach dem XSI-Standard, den Du anführst. Die früheren Versionen konnten das nicht; es war einer der Gründe für die Entwicklung des Konkurrenzproduktes C-Shell.
Okay, damit dürfte »$(( ))« ausreichend allgemeingültig sein. Ich nehme alles zurück und behaupte das Gegenteil.

@Kamikaze: Es ging doch darum, ein allgemeines Shell-Skript zu schreiben. Zitat: »Ich würde das ungerne in Bash schreiben«
 
Also die bek$%&/te Bourne Shell von Solaris kann "$(( ))" nicht, aber wer hätte das bei der auch schon erwartet?
 
übrigends, weil hier auch entsprechendes Wissen vermittelt wurde:

Wo hast du denn dein Script überhaupt wie getestet?
Wenn ich das probiere, erhalte ich auf der Shell eine ganz erhebliche Anzahl von Fehlermeldungen, die meist auf solche Sachen deuten, wie sie dir hier schon vorgeführt wurden.
Zu der von dir geschilderten Fehlermeldung komme ich gar nicht.
Allerdings habe ich auch nicht eigens nachgesehen, welche Vorraussetzungen du verlangst, die ich vielleicht nicht bieten kann.

Es kommt mir aber merkwürdig vor, dass bei dir keine entsprechenden Fehler ausgeworfen werden, die wegen deiner Syntax garantiert kommen müssten.
 
#push, bekomme ich noch hilfe?
Nein. Du hast auf verschiedene Hinweise und aufgezählte Fehler nicht reagiert, sondern nur verlangt, jemand möge Dir eine fertig überarbeitete Fassung Deines Skriptes servieren. Du willst nicht "Shell lernen", weil Du überhaupt keine Ahnung davon hast, worum es geht. Das Skript hast Du irgendwo aufgetrieben, gemerkt, daß es ein Bash-Skript ist, das im FreeBSD-Basissystem mangels Bash nicht läuft, und willst es nun umgeschrieben haben.

So geht das hier nicht.
Tronar

PS: Braucht man MySQL für einen Gameserver?
 
Ich habe lediglich um eine überarbeiteten Version eines Teils
meines Scripts gebeten, um eine bessere Einsicht zu kriegen, was
ihr meint. Und das Script habe ich 100% selbst geschrieben. Ein Freund von
mir hat ein solches in bash geschrieben und ich habs dann in sh versucht.

PS: Braucht man MySQL für einen Gameserver?

Ja, für Metin2.
 
Zuletzt bearbeitet:
Deinen Einwand verstehe ich nun allerdings auch nicht.
Was willst du denn genau haben?
Alles, was da angeführt wurde (so weit ich das durchblicke) wurde doch sehr deutlich mit Beispielen gezeigt. Die Antworten sind teilweise sehr innig auf dein Script und enthaltene Fehler oder Ungereimtheiten eingegangen.

Der Gang der Dinge sollte nun sein, dass du es mit diesen Hinweisen versuchst und zurückmeldest, was du getan hast und welchen Erfolg oder Misserfolg das brachte. Im günstigsten Fall meldest du dich mit einem "Dankeschön, nun gehts, habe verstanden und es lag an dem und dem..."
Genaue Lösungen für DEIN Problem musst DU erarbeiten und alle sind froh, wenn du deine Fortschritte und Erfolge auch dokumentierst, damit anschließend andere an diesem Beispiel auch was lernen können.

Was glaubst du? Dass ich mich hinsetze und meinen PC so umbaue, dass er für dein Script die taugliche Umgebung liefert und es dann teste und verbessere, bis ich keinen Fehler mehr sehe um es dir dann zu liefern?
Nun, ich bin dazu viel zu unbedarft und könnte das gar nicht, aber ich würde es auch garantiert nicht machen und jemand, der mit eigenen Projekten beschäftigt ist und vielleicht etwas entwickelt, das ihm wichtig ist, wird das sicher nicht anders handhaben. Ich bin froh, wenn ich MEINEN PC für mich nutzen kann und MEINE Scripte darauf zum Laufen bringe.

Du solltest nun versuchen, die Beiträge zu verstehen, die dir helfen wollten und das in dein Script einarbeiten. Du solltest dann mit Option -x starten und jemand erwähnte etwas von einem set -e (ich erinnere das nun nicht genau, lies es nach, wie ich es bei nächster Gelegenheit auch machen werde!) womit erst mal das Script zähmen kannst und nicht direkt den blanken Wahnsinn produzierst. Du siehst dann selbst, wo was fehlt und dann kannst du gegen steuern und weiter verbessern und sehen und lernen und dann wieder fragen, wenn du neue Fragen hast.

Die alten Fragen wurden meiner Ansicht nach hier sehr umfangreich beantwortet und ich muss zugeben, dass mich deine neuerliche Anfrage ohne jede weitere Rückmeldung und Anstrengung deinerseits durchaus verärgert und ich mich auch deswegen nun so Wortreich melde, um einfach Dampf abzulassen und Frust loszuwerden.
Was glaubst du, wie die Beiträge derer zu Stande kommen, die dir hilfreiche Tips geben? Meinst du, die haben das einfach so herumliegen und schieben es nun mal eben in deinen Thread? Die haben gearbeitet, Zeit und Ressourcen investiert um dir zu helfen! Nun ist es aber mal an dir! Mach hin und schieb mal was nach, anstatt einfach Lösungen zu fordern.
Also ehrlich...
 
Zurück
Oben