Hinweis: Das Forum wird geschlossen! Neue Registrierungen sind nicht mehr möglich!

 Zurück zu Pro-Linux   Foren-Übersicht   FAQ     Suchen    Mitgliederliste
Shellprogrammierung - Übergabe eines Dateidescriptors an ein Script
Gehen Sie zu Seite 1, 2  Weiter
 
Neuen Beitrag schreiben   Auf Beitrag antworten    Pro-Linux Foren-Übersicht -> Programmieren - Allgemein
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 01. März 2014 21:09   Titel: Shellprogrammierung - Übergabe eines Dateidescriptors an ein Script

Hallo,

zum Hintergund bitte ich, das mal durchzulesen

http://debianforum.de/forum/viewtopic.php?f=29&t=148074

Ich wende mich also an die Experten hier mit meiner Frage: Was mache ich bei der Übergabe der Datei an das Script falsch? Oder gehe ich da von einem prinzipiell falschen Ansatz aus?
 
Benutzer-Profile anzeigen Private Nachricht senden

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 01. März 2014 22:16   Titel:

Zunächst mal: echo '$@' bewirkt, dass $@ ausgeben wird. Du suchst vermutlich "$@". Und: Wohin sollte das Skript diesen String ausgeben? Skripte öffnen von selbst keine Fenster, das musst du explizit mit xterm -e /bin/echo "$@" o.ä. tun.

Dann willst du keinen Dateidescriptor übergeben, sondern einen Dateinamen. Das ist ein sehr großer Unterschied. Ein Dateidescriptor ist einfach nur eine Zahl, die für einen Ein-/Ausgabekanal in einem Programm steht. Damit willst du normalerweise auf Shell-Ebene nichts zu tun haben, brauchst du für dein Problem auch nicht.

Der Grund für diese Fehlermeldung ist vermutlich, dass dein Skript nicht ausgeführt werden kann. Kannst du es auf der Kommandozeile aufrufen? Wenn ja: Das Sonderzeichen ~ wird nur von Shells ausgewertet, oder das Programm unterstützt es explizit. Gib da bei RapidSVN einen absoluten Pfad an.
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 01. März 2014 22:31   Titel:

Nee, nee, das läuft schon alles in einer Shell, also ich tippe im Terminal ein:
:
Code:
hk@Melina:~$ rapidsvn


RapidSVN startet, ich klicke halt irgendeine Datei an und wähle "Bearbeiten" oder drücke F3. RapidSVN startet das Script, übergibt ihm die Datei (oder eben nicht?), die Fehlermeldung (im selben Terminal) kommt eindeutig vom Script:

Code:
/home/hk/RapidSVN_prog.sh: Zeile 3: echo: Schreibfehler: Ungültiger Dateideskriptor.


Egal, was ich da schreibe, wie gesagt. Ich hab's ja z.B. auch mit $1 probiert (eben das erste übergebene Argument) - dieselbe Fehlermeldung. Offensichtlich wird dort ein Dateideskriptor erwartet, der nicht ankommt.

Also: Ich würde ja gerne mal den Befehl sehen, den RapidSVN da zusammenbastelt. Aus den Einträgen in der ~/.RapidSVN:

Code:
[Preferences]
StandardEditor=/home/hk/RapidSVN_prog.sh
AlwaysStandardEditor=1
StandardEditorArgs=%1

(Hierbei steht %1 für die übergebene Datei. Deskriptor, nehme ich an, nicht /pfad/dateiname, oder?)
 
Benutzer-Profile anzeigen Private Nachricht senden

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 01. März 2014 23:09   Titel:

wodim hat folgendes geschrieben::
Code:
/home/hk/RapidSVN_prog.sh: Zeile 3: echo: Schreibfehler: Ungültiger Dateideskriptor.

Ahaa! Also meldet nicht RapidSVN "ungültiger Dateideskriptor", sondern das Shellskript, genauer das echo. Und das liegt vermutlich daran, dass die Standardausgabe dieses Skriptes nicht offen ist - RapidSVN hat sie zugemacht - du kannst an dieser Stelle nichts ausgeben. Versuche die Ausgabe des echo in eine Datei umzuleiten oder in die Standardfehlerausgabe (mittels >&2), die siehst du ja offensichtlich.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 01. März 2014 23:15   Titel:

Janka hat folgendes geschrieben::
wodim hat folgendes geschrieben::
Code:
/home/hk/RapidSVN_prog.sh: Zeile 3: echo: Schreibfehler: Ungültiger Dateideskriptor.

Ahaa! Also meldet nicht RapidSVN "ungültiger Dateideskriptor", sondern das Shellskript, genauer das echo. Und das liegt vermutlich daran, dass die Standardausgabe dieses Skriptes nicht offen ist - RapidSVN hat sie zugemacht - du kannst an dieser Stelle nichts ausgeben. Versuche die Ausgabe des echo in eine Datei umzuleiten.

Langsam, langsam, ich bin ja gerade mal fertig mit dem Korrigieren meines letzten Beitrags. Wink

Also wenn ich das richtig sehe, hat nicht RapidSVN die Standardausgabe für das Script zugemacht, sondern es gab nie eine? (RapidSVN startet das Script, nicht ich. Würde ja zum Testen nichts nützen - wenn ich's aufrufe und ihm meinetwegen /pfad/dateiname als String übergebe, weiß ich, dass "echo $1" das ausgibt.)
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 01. März 2014 23:22   Titel:

Janka hat folgendes geschrieben::
Versuche die Ausgabe des echo in eine Datei umzuleiten oder in die Standardfehlerausgabe (mittels >&2), die siehst du ja offensichtlich.

Jo, das kam auch erst, nachdem ich schon mit Zitat geantwortet hatte. Wink Werd' ich machen, aber erst mal gut's Nächtle, schlag' ich vor.
 
Benutzer-Profile anzeigen Private Nachricht senden

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 02. März 2014 1:20   Titel:

wodim hat folgendes geschrieben::
Also wenn ich das richtig sehe, hat nicht RapidSVN die Standardausgabe für das Script zugemacht, sondern es gab nie eine?

Normalerweise "erben" Kindprozesse alle Filedescriptoren des Vaters zum Zeitpunkt des fork(), auch die Standardausgabe. Es ist eine übliche Maßnahme, diese zwischen fork() und exec() zu schließen oder auf andere Descriptoren umzubiegen, z.B. um mit dem Kind zu kommunizieren.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 02. März 2014 2:00   Titel:

Ähm, ich glaub' ich hab' auch wieder mal Schlafstörungen. Wink Am besten überlegen wir doch mal, was man sich da so zur Laufzeit alles angucken sollte. Da gibt's doch tolle Befehle ...

Hier mal eine meiner "Baustellen", also ein Teil von dem, was ich mir für meine Scripte so aus dem Netz zusammenkopiert und -gebastelt habe (das Problem der Fehlerfreiheit ist ein ebenso interessantes wie ungelöstes in der theoretischen Informatik, hab' ich mal gelesen. Darf mich ja auch seit ein paar Jährchen "Dipl.-Ing. f. Informationstechnik" nennen, manchmal fällt mir das doch wieder ein.) Wink Nutzung auf eigene Verantwortung natürlich, Korrekturen / Verbesserungen dringend erwünscht. Es darf auch gelacht werden. Wink

Code:
# /bash_libs/common

errCancel () {         # Abbruch bei Fehler         
   if  [ $1 != 0 ]; then beep -l 200 -f 1200; echo Abbruch mit Fehler $1;
   exit $1
fi
}

user_input (){        # Usereingabe (1 Zeichen ohne Enter)
   beep; read -n 1 -p "$1" x
   echo $x
}


################## Prozesshandling

pid_from_command () {    # PID eines laufenden Prozesses aus Komandozeile ermitteln

   line=`ps ax | grep "$1" | grep -v 'grep'| grep -v 'S+'`

   # Beispiel ohne "| grep -v 'S+'" (erste Zeile wird gebraucht):
   # 5658 pts/1    SLs+   2:31 mplayer http://mp3.webradio.rockantenne.de:80
   # 5659 pts/1    S+     0:03 mplayer http://mp3.webradio.rockantenne.de:80

   if [ $? == 0 ]; then      
      echo $(echo $line | cut -d" " -f1)
   else
      echo 0 # Prozess nicht gefunden
   fi      
}

kill_from_command () {  # Prozess aus Kommandozeile ermitteln und killen

   pid=`pid_from_command $1`
   kill $pid
   echo $?
}


################## Fensterhandling

wid_from_command () {     # Fenster-Id aus Kommandozeile ermitteln

### Achtung: wenn z.B. ps ax "icedove" velangt, dann wmctrl "Icedove" ###

   wid=`wmctrl -l -x | grep $1 | cut -d" " -f1`

   if [ $wid != '' ]; then      
      echo $wid
   else
      echo 0 # Kein Fenster gefunden
   fi
}


wid_from_pid () {       # Fenster-Id aus Prozess-Id ermitteln

   wid=`wmctrl -p -l | grep "$1" | cut -d" " -f1`

   if [ $wid != '' ]; then      
      echo $wid
   else
      echo 0 # Kein Fenster gefunden
   fi
}


recoverWindow () {       # Fenster wiederherstellen, $1: Fenster-Id

   wmctrl -i -a $1

}


closeWindow () {       # Fenster schließen, $1: Fenster-Id

   wmctrl -i -c $1

}

closeWindow_wait_for_end () { # Fenster schließen und Warten, bis Prozess beendet
                       # $1: Fenster-Id, $2: Startkommando         
   closeWindow $1

   while [ $? == 0 ]; do                         

      ps ax | grep $2 | grep -v 'grep'

   done
}

################# Dateioperationen

addLine () {   # String $1 als Zeile an Datei $2 anhängen           
   echo $str >> $2; errCancel $?
}


delLine () {    # Zeile mit String $1 aus Datei $2 löschen - Achtung: Wenn Datei nicht gefunden, wird sie angelegt!
   grep -v $1 $2 > /tmp/tempdatei; errCancel $?
   mv /tmp/tempdatei $2; errCancel $?
}



set_date () { # Dateidatum von Datei $1 auf $2 setzen

# Eingabe $2: dd.mm.yy, touch verlangt yymmdd

touch --date=${2:6:2}${2:3:2}${2:0:2} $1
   
# touch --date=060826 datei
# touch -t 0610140915 datei

}


##################### Strings formatieren

repl_chars () {                # In String $1 Zeichen $2 durch $3 ersetzen
   echo ${1//$2/$3}
}

date_unformat () {                  # Eingabe: yyyy*mm*dd
   echo ${1:8:2}.${1:5:2}.${1:0:4}   # Ausgabe: dd.mm.yyyy
}
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 02. März 2014 4:09   Titel:

Janka hat folgendes geschrieben::
Zunächst mal: echo '$@' bewirkt, dass $@ ausgeben wird. Du suchst vermutlich "$@"

Nein.
Code:
echo $@ >&2

liefert (Beispiel):
Code:
/mnt/data/Geraete/HiFiRack/pre/AmpLog/amp_log.asc

Code:
echo $1 >&2

übrigens auch. Wie hieß das doch gleich - "Probieren geht über Studieren" oder so ähnlich ... Jetzt sollte der Rest ein Vergnügen sein. Danke. Wink
_________________
Mit einem Computer kann man Probleme lösen, die man ohne ihn nicht hätte.
 
Benutzer-Profile anzeigen Private Nachricht senden

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 02. März 2014 15:52   Titel:

wodim hat folgendes geschrieben::
Janka hat folgendes geschrieben::
Zunächst mal: echo '$@' bewirkt, dass $@ ausgeben wird. Du suchst vermutlich "$@"

Nein.
Code:
echo $@ >&2


Doch. echo $@ ist etwas anderes als echo '$@', wie anderswo von dir selbst geschrieben, und wieder etwas anderes als echo "$@".

$ man bash, Abschnitt QUOTING.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 02. März 2014 17:05   Titel:

Janka hat folgendes geschrieben::
wodim hat folgendes geschrieben::
Janka hat folgendes geschrieben::
Zunächst mal: echo '$@' bewirkt, dass $@ ausgeben wird. Du suchst vermutlich "$@"

Nein.

Doch. echo $@ ist etwas anderes als echo '$@', wie anderswo von dir selbst geschrieben, und wieder etwas anderes als echo "$@".

Ja und? Gesucht habe ich lediglich eine Möglichkeit, festzustellen, was da übergeben wird (s. Titel des ganzen Threads hier), Wink und wie das zu handeln ist, damit eben das aufgerufene Programm die übergebene Datei öffnet. Und das war schließlich konkret so zu sehen:
Zitat:
echo $@ >&2

Also hab' ich mich für deinen Tipp bedankt: Mein Script hat als Kindprozess keine Standardausgabe, das also mal auf die Standard - Fehlerausgabe umleiten - damit war alles klar. Schon vergessen? Also fang' jetzt bloß nicht an, Krümel zu kacken oder die eckige Wahrheit rund biegen zu wollen, nur um unbedingt "Recht zu behalten". Mit solchen Leuten zu diskutieren ist nämlich absolut sinnbefreit.

So sieht mein Script übrigens jetzt aus:

Code:
#!/bin/bash
# . /bash_libs/common

# Programm aus RapidSVN starten, s. Eintrag "Standardeditor" in ~/.RapidSVN
# $1: Übergebene Datei (mit Pfad)

#### echo $1 >&2 ###

case $1 in

   *.asc) # LTSpice oder gedit

      liste='TRUE LTSpice FALSE gedit'
      prog=$(zenity --width=250 --height=190 --title="RapidSVN" --text="Spice-Schaltung bearbeiten mit:" --list --radiolist --column="" --column="" $liste)       

      if [ $prog == 'LTSpice' ]; then

         winpath=${1//'/mnt/data'/'D:'}                # /mnt/data ist Wine - Laufwerk D
         winpath=${winpath//'/'/'\\'}                  # Slashs durch doppelte Backslashs ersetzen
         wine 'C:\Program Files\LTC\LTspiceIV\scad3.exe' $winpath

      elif [ $prog == 'gedit' ]; then
         gedit $1
      fi
   ;;

   # *.bmp|*.jpg)

   *.wav|*.mp*) audacity $1 ;;

   *) # alles andere -> Standardeditor
      gedit $1
   ;;

esac

Das einzige "Problem" noch: LTSpice wird neu gestartet (und wenn's auch schon mit derselben Datei läuft), gedit öffnet in diesem Fall die Datei in einem neuen Tab. Oder präsentiert mir eben den, wenn er schon existiert. So reagiert eben jedes Programm auf seine Weise - von audacity reden wir also lieber gar nicht erst Wink ...

Janka hat folgendes geschrieben::
$ man bash, Abschnitt QUOTING.

Danke, die Manpages meide ich gewöhnlich zu Gunsten etwas "lebendigerer" (und überwiegend deutschsprachiger) Seiten, wie eben z.B. dieser hier. Wink Als alter Deutscher halt. Wink

Spätestens jetzt fände ich es also angebracht, die Administration hier mal über das nächste Auftreten des seit mehr als 10 Jahren netzbekanntesten Trolls zu infomieren. Wink Aber vorher sich mal über den:

http://www.politik-sind-wir.de/showthread.php/36473-Das-Ende-der-Europ%C3%A4ischen-Union?p=106357&viewfull=1#post106357
_________________
Mit einem Computer kann man Probleme lösen, die man ohne ihn nicht hätte.


Zuletzt bearbeitet von wodim am 03. März 2014 1:01, insgesamt 1-mal bearbeitet
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 02. März 2014 20:35   Titel:

wodim hat folgendes geschrieben::
Code:
echo $@ >&2

liefert (Beispiel):
Code:
/mnt/data/Geraete/HiFiRack/pre/AmpLog/amp_log.asc

Code:
echo $1 >&2

übrigens auch.

Aber sobald ein Leerzeichen im Pfad oder Dateinamen auftaucht, wird der String da abgehackt. Bei $1, nicht bei $@.

Wer hat eine plausible Erklärung dafür?
_________________
Mit einem Computer kann man Probleme lösen, die man ohne ihn nicht hätte.
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 03. März 2014 0:42   Titel:

Janka hat folgendes geschrieben::
Dann willst du keinen Dateidescriptor übergeben, sondern einen Dateinamen.

Hm, will ich. Bin beim Forschen Wink Praktisch jedes Programm nimmt den nur bis zum ersten Leerzeichen an. Alles, was danach kommt, wird entweder ignoriert oder als zweites [, drittes, viertes, ...] Argument interpretiert. Das äußert sich z.B. so:

Code:
iceweasel /pfad/dat ei name.html

Da will Iceweasel (Firefox für Debian) Wink ganz korrekt eine Seite mit dem Link "file:///pfad/dat" öffnen, die's natürlich nicht gibt.

Code:
gedit /pfad/dat ei name.txt

Der Editor präsentiert mir drei (natürlich leere) Tabs, überschrieben mit den "Dateinamen" "dat", "ei" und "name.txt".

Na, und so weiter ... Meine selbstgebastelten Funktionen erst noch ...

Also wie lässt sich ein Dateiname (oder allgemein ein String mit Leerzeichen) korrekt als ein Argument übergeben? Im Terminal doch ganz einfach:
Code:
gedit '/pfad/dat ei name.txt'


Im Script funktioniert
Code:
gedit '$datei'
schon wieder nicht mehr, wenn der Wert von $datei ein String mit Leerzeichen ist.

Wiederum:
Code:
case $@ in

   *.asc) anweisung(en) ;;

-
-
-
esac


Das packt's komischerweise. Und das macht das Script / die Shell doch auch nicht alleine, da wird doch auch ein Programm aufgerufen, oder?

Mir schwant langsam: Das Ganze lässt sich doch sicher ganz elegant umgehen, wenn man keinen String, sondern einen Dateideskriptor übergibt (wie offenbar RapidSVN meinem Script) - aber wie?

(Aus höheren Sprachen wie C, VB, ... ist mir Analoges geläufig als "Kontext", "Call by Reference", "Pointer" oder wie auch immer. Und irgendwie muss sich das wohl hinter dem geheimnisvollen Argument %1 verstecken - das sehe ich bei RapidSVN auch beileibe nicht zum ersten Mal) ...
_________________
Mit einem Computer kann man Probleme lösen, die man ohne ihn nicht hätte.
 
Benutzer-Profile anzeigen Private Nachricht senden

wodim



Anmeldungsdatum: 01.03.2014
Beiträge: 17
Wohnort: Gilching

BeitragVerfasst am: 03. März 2014 15:26   Titel:

wodim hat folgendes geschrieben::
Also hab' ich mich für deinen Tipp bedankt: Mein Script hat als Kindprozess keine Standardausgabe, das also mal auf die Standard - Fehlerausgabe umleiten - damit war alles klar. Schon vergessen? Also fang' jetzt bloß nicht an, Krümel zu kacken oder die eckige Wahrheit rund biegen zu wollen, nur um unbedingt "Recht zu behalten". Mit solchen Leuten zu diskutieren ist nämlich absolut sinnbefreit.

Solltest du also auf Grund meiner "Kritik" die beleidigte Leberwurst spielen, dann schau' doch mal wieder hier 'rein, wenn du dich ausgetrotzt hast:

http://debianforum.de/forum/viewtopic.php?f=29&t=148074&p=979085#p979065

So etwa ist meine naive Vorstellung von einer konstruktiven Diskussion zu verstehen. Wink
_________________
Mit einem Computer kann man Probleme lösen, die man ohne ihn nicht hätte.
 
Benutzer-Profile anzeigen Private Nachricht senden

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 03. März 2014 16:01   Titel:

wodim hat folgendes geschrieben::
Also fang' jetzt bloß nicht an, Krümel zu kacken

Fehler passieren mir doch auch dauernd und da bin ich froh, wenn mich jemand auf den Irrtum hinweist. Sonst bleibt der nämlich stehen und der nächste der es liest macht ihn nach.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

Beiträge vom vorherigen Thema anzeigen:   
     Pro-Linux Foren-Übersicht -> Programmieren - Allgemein Alle Zeiten sind GMT + 1 Stunde
Gehen Sie zu Seite 1, 2  Weiter
Seite 1 von 2

 
Gehen Sie zu:  

Powered by phpBB © phpBB Group
pro_linux Theme © 2004 by Mandaxy