[gelöst] Einfache Bash-Script Frage

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Prometheuss
Beiträge: 158
Registriert: 10.02.2015 21:45:52

[gelöst] Einfache Bash-Script Frage

Beitrag von Prometheuss » 02.06.2015 23:31:24

Hallo Freunde,
ich hab ein Bash-Script geschrieben welches Verzeichnisse archivieren und komprimieren soll. Funktioniert alles wunderbar (mein erstes Sinnvolles script Hurra :mrgreen: :mrgreen: :mrgreen: ) außer eine kleine Sache.
Wenn ich alles sinngemäß eingebe, fordert mich die Shell auf, einen Befehl einzugeben. ich antworte meist mit exit und das script läuft dann wie geplant. hier die ersten Zeilen wo der Fehler stecken sollte (alles dannach sind nur if und elif then else anweisungen die Funktionieren). Ich hab auch nix in ne subshell gepackt, zumindest nicht, dass ich wüsste, außer halt die Shebang-Zeile #/bin/bash )

(ob es jetzt Sinn macht das archiv in /tmp zu stecken is erstmal Egal, das script selbst dient nur der übung :lol: Falls es aber was Sinnvolles neben /tmp gibt und nicht im Home verzeichnis liegt bin ich für jede Anregung dankbar)

Code: Alles auswählen

 
 11 opt=$1
 12 Dir=$2
 13 archiv=/tmp/archiv
 14 if [ $# != 2 ] 
 15     then
 16         echo "Benötigt wird ein Operand und eine Verzeichn    isangabe!"
 17         exit 1
 18 fi                     
 19
 20 ls $archiv >/dev/null 2>&1
 21 if [ $? != 0 ] 
 22     then mkdir $archiv >/dev/null
 23 fi

Zuletzt geändert von Prometheuss am 03.06.2015 23:37:08, insgesamt 1-mal geändert.
~ein Teil dieser Antwort könnte sie verunsichern.

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Einfache Bash-Script Frage

Beitrag von NAB » 03.06.2015 01:52:55

Prometheuss hat geschrieben:mein erstes Sinnvolles script Hurra :mrgreen: :mrgreen: :mrgreen:
Find ich klasse! :THX:
Aber ...
Prometheuss hat geschrieben:Wenn ich alles sinngemäß eingebe, fordert mich die Shell auf, einen Befehl einzugeben. ich antworte meist mit exit und das script läuft dann wie geplant.
ich versteh die Fehlerbeschreibung leider nicht :-/

Wie startest du das Script? Ich würd am Anfang ein "#!/bin/bash" erwarten.
Prometheuss hat geschrieben:außer halt die Shebang-Zeile #/bin/bash
Ist das vielleicht schon der Fehler? (Da fehlt ein Ausrufezeichen)

Und wo ich schon dabei bin ... hier testest du, ob das Verzeichnis existiert, oder?

Code: Alles auswählen

   13 archiv=/tmp/archiv
 20 ls $archiv >/dev/null 2>&1
 21 if [ $? != 0 ] 
 22     then mkdir $archiv >/dev/null
 23 fi
Das ist raffiniert!

Die Bash hat eine lange Liste an Datei-Test-Operatoren:
http://tldp.org/LDP/abs/html/fto.html
So würdest du dir also einen ls-Aufruf sparen:

Code: Alles auswählen

if [ ! -e $archiv ]
 then
    mkdir $archiv
fi
Und an der Länge der Liste an Operatoren siehst du schon, was alles schief gehen könnte ... /tmp/archiv könnte zum Beispiel eine Datei sein und kein Verzeichnis, oder nicht beschreibbar sein ... aber gut, solange es dein Backup-Script ist, kontrollierst du ja die Umgebung :)

Hartgesottene Charaktäre könnten da auch einfach ein "mkdir $archiv" hinschreiben und sich den Test sparen ... das Endergebnis wäre das selbe.
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Benutzeravatar
Meillo
Moderator
Beiträge: 9235
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Einfache Bash-Script Frage

Beitrag von Meillo » 03.06.2015 06:00:25

Einen Fehler habe ich in dem Ausschnitt nicht gefunden, aber da fehlt doch noch ein Teil, oder? Dieses Script archiviert ja noch nichts.
Prometheuss hat geschrieben:

Code: Alles auswählen

 
 11 opt=$1
 12 Dir=$2
 13 archiv=/tmp/archiv
 14 if [ $# != 2 ] 
 15     then
 16         echo "Benötigt wird ein Operand und eine Verzeichn    isangabe!"
 17         exit 1
 18 fi                     
 19
 20 ls $archiv >/dev/null 2>&1
 21 if [ $? != 0 ] 
 22     then mkdir $archiv >/dev/null
 23 fi
Ein paar Anmerkungen:
- Variablenexpansionen sollte man fast immer quoten ("$var")
- Deine Einrueckung ist inkonsistent. (Entweder das `then' an den Zeilenanfang oder mit Strichpunkt ans Ende der vorigen Zeile.)
- Fuer Usage-Meldungen gibt es eine best-practice. (Siehe unten.)
- Wenn du das Verzeichnis sowieso anlegen willst, dann musst du nicht hartgesotten sein um `mkdir -p' zu verwenden. ;-) (Das erzeugt auch keine Race-Condition, btw.)

Hier mal mein Vorschlag, wie ich dein obiges Stueck Code schreiben wuerde:

Code: Alles auswählen

#!/bin/bash
# Kurze Beschreibung was das Script tut

if [ $# != 2 ] ; then
        echo "Usage: ${0##*/} opt dir" >&2
        exit 1
fi                     
opt="$1"
dir="$2"
archiv=/tmp/archiv

mkdir -p "$archiv"
Use ed once in a while!

Benutzeravatar
Prometheuss
Beiträge: 158
Registriert: 10.02.2015 21:45:52

Re: Einfache Bash-Script Frage

Beitrag von Prometheuss » 03.06.2015 16:52:51

NAB hat geschrieben:ich versteh die Fehlerbeschreibung leider nicht :-/

Wie startest du das Script? Ich würd am Anfang ein "#!/bin/bash" erwarten.
Also die Shebang is schon richtig, ich hab grad nur beim beschreiben das Ausrufezeichen vergessen, sorry. :facepalm:
Folgendes passiert:

Code: Alles auswählen

user@machine:~$ ./backup-test save /dateixy # save is ne option die später im Script kommt, aber da funktioniert alles
user@machine:~$ exit                                   #das "exit" schreibe ich, weil es den anschein macht als ob mein Befehl nicht ankam..
exit
tar: Entferne führende „/“ von Elementnamen
/home/user/übung
/home/user/übung/test.txt
Backup erstellt
Backup heißt /tmp/archiv/3.Jun_2015.tar.gz
Man erkennt, alles läuft und erfüllt sein zweck, doch dieser exit Befehl den ich weiterreichen muss verwirrt mich :S
NAB hat geschrieben:Und wo ich schon dabei bin ... hier testest du, ob das Verzeichnis existiert, oder?
ja stimmt genau, ich hätte auch if [ -e /tmp/archiv] schreiben können, ich bin mir aber noch nicht so sicher mit dem test befehl. daher hab ichs mal mit ls /tmp/archiv versucht, funktioniert auch erstmal. vielleicht rührt daher die Fehlermeldung..
Meillo hat geschrieben:Einen Fehler habe ich in dem Ausschnitt nicht gefunden, aber da fehlt doch noch ein Teil, oder? Dieses Script archiviert ja noch nichts.
das stimmt, der Teil kommt dannach, der funktioniert aber.
Meillo hat geschrieben:Hier mal mein Vorschlag, wie ich dein obiges Stueck Code schreiben wuerde:

Code: Alles auswählen
#!/bin/bash
# Kurze Beschreibung was das Script tut

if [ $# != 2 ] ; then
echo "Usage: ${0##*/} opt dir" >&2
exit 1
fi
opt="$1"
dir="$2"
archiv=/tmp/archiv

mkdir -p "$archiv"
wofür isn die Variable ${0##*/} ?
~ein Teil dieser Antwort könnte sie verunsichern.

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: Einfache Bash-Script Frage

Beitrag von rendegast » 03.06.2015 17:26:47

/tmp/archiv ist ja wunderbar für eine Attacke, besser

Code: Alles auswählen

TDIR=$(mktemp -d)

..... mache was mit $TDIR ...

rm -rf $TDIR
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

inne
Beiträge: 3289
Registriert: 29.06.2013 17:32:10
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Re: Einfache Bash-Script Frage

Beitrag von inne » 03.06.2015 17:32:20

rendegast hat geschrieben:/tmp/archiv ist ja wunderbar für eine Attacke, besser

Code: Alles auswählen

TDIR=$(mktemp -d)

..... mache was mit $TDIR ...

rm -rf $TDIR
Das mit der Symlink-Schwachstelle ist richtig – auch wenns keine Datei ist! Aber noch besser ist:

Code: Alles auswählen

tempdir=$(mktemp -d) || exit
trap "rm -rf -- '$tempdir'" EXIT INT TERM
..... mache was mit $tempdir ...

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: Einfache Bash-Script Frage

Beitrag von Cae » 03.06.2015 17:36:01

Prometheuss hat geschrieben:Folgendes passiert:

Code: Alles auswählen

user@machine:~$ ./backup-test save /dateixy # save is ne option die später im Script kommt, aber da funktioniert alles
user@machine:~$ exit                                   #das "exit" schreibe ich, weil es den anschein macht als ob mein Befehl nicht ankam..
exit
tar: Entferne führende „/“ von Elementnamen
[...]
Ich behaupte, du rufst da irgendwo bash, $SHELL o.ae. auf, welches eine (interaktive) Subshell startet, die solange blockt, bis du sie mit exit (bzw. EOF, also ^D) verlaesst.

Das kann man nun durch set -x, Debianstrace oder durch Draufschauen genauer eingrenzen.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Einfache Bash-Script Frage

Beitrag von NAB » 03.06.2015 19:31:15

Also ich sehe da auch keinen Fehler. Entweder habe ich Tomaten auf den Augen (kann mal vorkommen), oder das Problem wird weiter unten im Script verursacht.

Durch Sachen wie ">/dev/null 2>&1" verhinderst du aber auch gleich, dass du sehen kannst, wie weit das Script kommt ... sowas würde ich, wenn überhaupt nötig, erst einfügen, wenn alles reibungslos läuft.
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Benutzeravatar
Prometheuss
Beiträge: 158
Registriert: 10.02.2015 21:45:52

Re: Einfache Bash-Script Frage

Beitrag von Prometheuss » 03.06.2015 21:27:09

NAB hat geschrieben:Also ich sehe da auch keinen Fehler. Entweder habe ich Tomaten auf den Augen (kann mal vorkommen), oder das Problem wird weiter unten im Script verursacht.

Durch Sachen wie ">/dev/null 2>&1" verhinderst du aber auch gleich, dass du sehen kannst, wie weit das Script kommt ... sowas würde ich, wenn überhaupt nötig, erst einfügen, wenn alles reibungslos läuft.
ich hab schon versucht mittels sh -x einen Fehler zu finden, komm damit aber nicht klar.
Ich habs jetzt einfach so gemacht: Alle Zeilen bis zur 22. neu geschrieben und nochmal probiert. Keine Ahnung was da Schief ist, aber jetzt funktionierts :lol: yea :D
ich Danke euch allen nochmal für die Hilfe
inne hat geschrieben:
rendegast hat geschrieben:/tmp/archiv ist ja wunderbar für eine Attacke, besser

Code: Alles auswählen

TDIR=$(mktemp -d)

..... mache was mit $TDIR ...

rm -rf $TDIR
Das mit der Symlink-Schwachstelle ist richtig – auch wenns keine Datei ist! Aber noch besser ist:

Code: Alles auswählen

tempdir=$(mktemp -d) || exit
trap "rm -rf -- '$tempdir'" EXIT INT TERM
..... mache was mit $tempdir ...
Hey inne die Zeilen an Code versteh ich grad nicht so richtig :S willst du mir das nochmal erklären? Also nur die Variable TDIR und der trap part.
ps. da is ein nettes Palindrom :D
~ein Teil dieser Antwort könnte sie verunsichern.

inne
Beiträge: 3289
Registriert: 29.06.2013 17:32:10
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Re: Einfache Bash-Script Frage

Beitrag von inne » 03.06.2015 22:47:49

Die Variable ist für die Pfadangaben da und enthält den Pfad zum temp. Verzeichnis. Das trap führt das übergebene Kommando aus, sobald das Skript beendet oder falls es abgebrochen ist – rm, damit das temp. Verzeichnis nicht verweist.

PS:
trap part :-)

Benutzeravatar
Prometheuss
Beiträge: 158
Registriert: 10.02.2015 21:45:52

Re: Einfache Bash-Script Frage

Beitrag von Prometheuss » 03.06.2015 23:36:43

inne hat geschrieben:Die Variable ist für die Pfadangaben da und enthält den Pfad zum temp. Verzeichnis. Das trap führt das übergebene Kommando aus, sobald das Skript beendet oder falls es abgebrochen ist – rm, damit das temp. Verzeichnis nicht verweist.

PS:
trap part :-)
Dankeschöön :D
Nochmal so am Rande, gibt es ne gute Alternative zu /tmp wo ich das Backup hinpacken könnte? /home wär blöd wenn ich ein backup von /home machen würde was wahrscheinlicher ist als ein backup von tmp :lol:

ps. Gefällt mir!
~ein Teil dieser Antwort könnte sie verunsichern.

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Einfache Bash-Script Frage

Beitrag von NAB » 04.06.2015 01:43:57

Prometheuss hat geschrieben:Ich habs jetzt einfach so gemacht: Alle Zeilen bis zur 22. neu geschrieben und nochmal probiert. Keine Ahnung was da Schief ist, aber jetzt funktionierts :lol: yea :D
Hat dafür jemand eine Erklärung? (Ich hab nämlich keine)
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: Einfache Bash-Script Frage

Beitrag von Cae » 04.06.2015 02:09:06

NAB hat geschrieben:
Prometheuss hat geschrieben:Ich habs jetzt einfach so gemacht: Alle Zeilen bis zur 22. neu geschrieben und nochmal probiert. Keine Ahnung was da Schief ist, aber jetzt funktionierts :lol: yea :D
Hat dafür jemand eine Erklärung? (Ich hab nämlich keine)
Noe, abweichend von meiner obigen Theorie (die wohl nicht zutrifft, da sie ignoriert wurde...) nicht. Spaetestens mit strace haette man aber gesehen, wer da blockt.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
Meillo
Moderator
Beiträge: 9235
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Einfache Bash-Script Frage

Beitrag von Meillo » 04.06.2015 09:22:30

Cae hat geschrieben:Noe, abweichend von meiner obigen Theorie (die wohl nicht zutrifft, da sie ignoriert wurde...) nicht. Spaetestens mit strace haette man aber gesehen, wer da blockt.
Und waere das komplette Script hier gepostet worden, dann haette er die Rolle von ``man'' noch nicht mal selbst uebernehmen muessen ... So aber bleibt es bei dem unbefriedigenden Endergebnis, dass es magischerweise ploetzlich tut und keiner weiss warum. Haben wir nun etwas gelernt?
Use ed once in a while!

Benutzeravatar
Prometheuss
Beiträge: 158
Registriert: 10.02.2015 21:45:52

Re: Einfache Bash-Script Frage

Beitrag von Prometheuss » 04.06.2015 16:08:01

Meillo hat geschrieben:
Cae hat geschrieben:Noe, abweichend von meiner obigen Theorie (die wohl nicht zutrifft, da sie ignoriert wurde...) nicht. Spaetestens mit strace haette man aber gesehen, wer da blockt.
Und waere das komplette Script hier gepostet worden, dann haette er die Rolle von ``man'' noch nicht mal selbst uebernehmen muessen ... So aber bleibt es bei dem unbefriedigenden Endergebnis, dass es magischerweise ploetzlich tut und keiner weiss warum. Haben wir nun etwas gelernt?
also, nochmal zu cae, ich weiß nicht wie strace funktioniert, daher hab ich sh -x verwendet. Ich hoff mal der Effekt wäre der selbe gewesen.

Das is jetzt echt peinlich aber wenn ihr des rätsels Lösung wollt: ich hab 2 Shebang-zeilen geschrieben und tatsächlich hab ich das #! zeichen bei der 2ten Zeile vergessen :oops:
NAB hat ja schon erwähnt, dass ich möglicherweise was vergessen hab, ich schrieb noch so; nein hab ich nicht. Das stimmt ja auch fast, die erste Zeile war vollständig aber die "2te" shebang war halt nur aus : /bin/bash
also
es tut mir einfach echt leid leute, Sorry :facepalm: :facepalm: :facepalm:
~ein Teil dieser Antwort könnte sie verunsichern.

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: [gelöst] Einfache Bash-Script Frage

Beitrag von NAB » 04.06.2015 16:15:04

Kein Problem ... wer noch nie :facepalm: gemacht hat, werfe den ersten Stein ;-)

Aber neugierig war ich schon, wie man das hinkriegt ... und die Antwort war ja nun auch entsprechend einfach :-)
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

Antworten