• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[solved] Bash: Skript mit Variablen-Problem

Ricardo

Newbie
hallo leute,

ich hab da ein riesen-problem mit einem skript bzw. mit der bash-syntax und zwar möchte ich als übergabeparameter ($1) eine variable angeben die im skript existiert und deren inhalt dann benutzt werden soll. das ganze besteht aus 2 teilen, einmal die serverliste und einmal das ausführungsskript. das skript sieht folgendermaßen aus:

# Server-Liste
source ~/serverlist

# Unterscheidung & Verbindungsteil
if [ ! $1 ]
then
echo "Unsupported Usage."
else
ssh $[$1]
fi

exit 0

die liste sieht so aus:

meinserver1='server1.domain.de'
meinserver2='server2.domain.de'
meinserver3='server3.domain.de'

wenn ich nun aber das skript aufrufe mit ./skriptname meinserver1, so kommt bei mir aber ständig die fehlermeldung:
server1.domain.de: expression recursion level exceeded (error token is "server1.domain.de")

kann mir da jemand weiterhelfen?

rgds,
ricardo
 
OP
Ricardo

Ricardo

Newbie
ich hab übrigens rausgefunden das ich mit $(($1)) die richtige ausgabe bekomme, nur dann erhalte ich wieder:

server1.domain.de: expression recursion level exceeded (error token is "server1.domain.de")

hilfe!
 

trooperle

Newbie
Tach mal wieder,

erstmal führe das Skript mit
bash -x <skriptname> aus oder oben in der ersten Zeile
#!/bin/bash -x

damit erzeugst du debug-output, evtl hilft dir das schon weiter.

Zum anderen
[ ! $1 ] soll vermutlich bewirken, daß du prüfst ob ein Argument mit übergeben wurde. Versuch es besser mal mit

if [ -z "$1" ]
then
...

( zero-length, daher das z )
damit prüfst du, ob der String "$1" leer ist. ist dies der fall, wird der then zweig, sonst der else-zweig ausgeführt.
mit -n "$1" prüfst du, ob der String nicht leer ist ( non-zero length )

Dei Anführungsstriche sind wichtig, sind die nicht gesetzt, kommt es schonmal zu fehlern.

Hoffe Dir damit geholfen zu haben

Trooperle
P.S: Versuch's mal mit "man test" oder "man bash", da findet man viele nützliche vergleichsoperatoren etc. Du kannst den Befehl test oder einfach [ <ausdruck> ] verwenden, die sind äquivlent
 
A

Anonymous

Gast
hm also das klappt leider nicht... bzw. es bringt keine verbesserung!

ich erhalte immernoch "skriptname: line 13: server1.domain.de: expression recursion level exceeded (error token is "server1.domain.de")

übrigens hatte ! $1 funktioniert, was mich als c++'ler sehr gefreut hat :p

hatte ich schon erwähnt das die bash-syntax die pure folter is? *G*

rgds,
ricardo
 

trooperle

Newbie
Sicher das das funktioniert? Welche Zeile ist denn Zeile 13?
Wie gesagt, probier es mal mit bash -x <skriptname>
Der Output ist gewöhnungsbedürftig, aber als C++'ler solltest Du ja undurchsitigen Code und Debugging gewohnt sein :lol:

Trooperle
 
OP
Ricardo

Ricardo

Newbie
trooperle schrieb:
Sicher das das funktioniert? Welche Zeile ist denn Zeile 13?
Wie gesagt, probier es mal mit bash -x <skriptname>
Der Output ist gewöhnungsbedürftig, aber als C++'ler solltest Du ja undurchsitigen Code und Debugging gewohnt sein :lol:

;) könnte man sagen japp

bash -x skriptname führte ja zu eben dem output... ohne irgendwie hilfreich zu sein leider

das problem ist die var! eben ssh $[$1] bzw. ssh $(($1))... beides führt dazu das er wohl den zugewiesenen wert erkennt aber er kann ihn nicht benutzen oder versucht ihn auszuführen oder wat weiß der geier...

rgds,
ricardo
 

nobbiew

Hacker
Folgendes sollte gehen
Code:
# Server-Liste 
source ~/serverlist 
 
# Unterscheidung & Verbindungsteil 
if [ ! $1 ] 
then 
 echo "Unsupported Usage." 
else 
eval ssh \$$1 
fi 
 
exit 0

Dein Problem liegt daran, dass die bash die Variablenevaluierung nur einmal macht. Mit eval bringst du ihn dazu, dass er nachdem er $1 evaluiert hat, das Ergebnis noch einmal evaluert. Du mit mit \$ jedoch verhindern, dass beim 1. mal das $$ als Prozessid interpretiert wird. Gilt übrigens für nahezu alle shell's.
 

nobbiew

Hacker
Da fällt mir noch was tückisches ein.

Falls du die Befehlszeile erweiterst und z.B. shell-variablen vom remote-Rechner verwenden willst, musst du ebenfalls darauf achten, dass die das $ mit \$ quotest, Sonst wird die variable lokal ausgewertet.
 
OP
Ricardo

Ricardo

Newbie
hmm, also wenn ich das 1-zu-1 übernehme klappt das nicht. ich hab auch verschiedene andere kombinationen probiert wie z.b.
eval `ssh \$$1`
oder
eval "ssh \$$1"
...

aber nix davon hat was gebracht. bei der 1-zu-1 kopie von deinem sourcecode hat sich sogar der ssh-interpreter mit der hilfeseite gemeldet die kommt wenn man einfach "ssh" eingibt an der shell...

rgds,
ricardo
 

nobbiew

Hacker
Versuchs mal damit
Code:
#!/bin/bash

# Server-Liste 
 source ~/serverlist 
   
 # Unterscheidung & Verbindungsteil 
 if [ ! $1 ] 
 then 
  echo "Unsupported Usage." 
 else 
 eval ssh \$$1 
 fi 
   
 exit 0

#!/bin/bash muss in der 1. Zeile stehen u. dahinter dürfen keine anderen Zeichen, auch nicht Leerzeichen kommen
 
OP
Ricardo

Ricardo

Newbie
heureka! genau das wars! oh maaaaaann... das is echt traurig...

(und ich hab mich immer gewundert was der kommentar in der ersten zeile zu suchen hat :D )

rgds,
ricardo
 

nobbiew

Hacker
Das ist die sog. shebang-Zeile (leg mich nicht auf die schreibweise fest)
muss immer in der 1. Zeile stehen
beginnt immer mit #!Programm
Programm steht für die shell o. interpreter (z.B. /usr/bin/perl), das das folgende Skript auswerten soll. Danach dürfen noch parameter zum programmaufruf des Interpreters kommen, aber keine Kommentare mehr, da alles nach dem #! bis zum Zeilenende als Programmaufruf verstanden wird.

Häufige shebang-Zeilen:
#!/usr/bin/perl -w
#!/bin/bash
#!/bin/bash -x

Was immer wieder tückisch ist, sind Textdateien, die von Windows kommen, da die als Zeilenende CrLf und nicht Lf wie die Unix-Derivate verwenden. Somit erkennt Linux das Zeilenende nicht richtig und es geht ebenfalls schief. Hier hilft das Kommando dos2unix, das solche Dateien Unix-konform umwandelt
 
OP
Ricardo

Ricardo

Newbie
ha! tausend dank, genau sowas hab ich gebraucht... hab nun zwar schon meine workstation auf linux umgerüstet mit windows in ner vmware machine aber für alle kollegen wird das 100%ig interessant :)

rgds,
ricardo
 
A

Anonymous

Gast
das shebang (jap, so wirds geschrieben @ nobbiew) brauch man nur, wenn das script mit einem anderen interpreter ausgeführt werden soll als man es aufruft, wenn man beispielsweise ein für bash geschriebenes script hat, das in der bash ausgeführt wird brauch man es nicht, schaden kanns aber auch nicht... wenn du aber einen interpreter angibst den es nicht gibt funzt in den meisten fällen gar nix...

#!/bin/sh funzt immer da sie bei einem "normalen" unix/linux immer da ist, allerdings ist der scriptstil anders und seeeehr gewöhnungsbedürftig, außer man kann c :D :D

mit set -x kannst du auch den debug anstellen.... dann brauchst du es später nur auskommentieren wenn du es nicht mehr brauchst...
 

nobbiew

Hacker
Hallo Loci,
das mag im speziellen Fall bei aufruf unter einer Benutzerkennung so sein. Wenn du dann allerdings versuchst so ein Skript beim hochfahren laufen zu lassen, fällst du damit auf die Nase. Deshalb sollte man die Shebang-Zeile immer setzen. Die ist z.B. auch für den Apache wichtig, wenn du keinen speziellen Handler im Verzeichnis oder auf die Endung gesetzt hast.
 
Oben