$0 / argv[0] per Bash script setzen

  • Hallo liebe Scriptexperten, ist es möglich per Bash irgendwie den Parameter $0 per Bash-Script zu setzen.


    Ich hab z.B ein file foo.sh

    Shell-Script
    1. #!/bin/bash
    2. echo $0


    Ein Aufruf von "./foo.sh" printet dann auch "./foo.sh"


    Ich möchte jetzt in Etwa folgendes machen:
    export $0 = "Hello World" ### mir ist klar das das nicht geht
    ./foo.sh


    Und nun soll "Hello World" von foo.sh ausgegeben werden.


    Gruß
    Roland

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

  • Wieso soll's denn unbedingt $0 sein? - Kannst du nicht einfach einen x-beliebigen anderen Variablennamen nehmen?


    Meines Wissens nach ist $0 einer der wenigen fest definierten Namen, die dafür gedacht sind, sich nicht ändern zu lassen. ;-)

    Hardware: Zalman HD160XT; Asus H97M-Plus, 1024MB RAM, Digital Devices Cine S2 (rev 7), Atric-Einschalter, NEC3520 DVD-Laufwerk, Samsung 256 GB SSD-Festplatte --> darauf yaVDR 0.6
    Hifi: Denon AVR4306, Samsung UE40ES6300

  • Leider steht das Zielprogramm fest (ist ein altes Cups-Backend) und es erwartet in $0 einen Inhalt wie "foo://xyz"


    $0 ist normalerweise der Name des Scriptes, d.h. wenn ich einen Link auf foo.sh mache (ln -s foo.sh bar.sh) und dann "./bar.sh" aufrufe, dann wird auch "./bar.sh" ausgegeben. (also der Parameter lässt sich modifizieren)


    Dies wird soweit ich auch von busybox ausgenutzt, damit die nur 1 Binary brauchen

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

    The post was edited 1 time, last by pram ().

  • Ja, das mit dem Link würde funktionieren, allerdings kommen in der Cups-URI Schrägstriche vor. Also es muss definitiv so was wie "foo://xyz" oder "socket://1.2.3.4" gesetzt werden können.
    Da die URI bei jedem Druckauftrag geschrieben werden soll, möchte ich da nicht wild auf der Platte rum schreiben.
    Leider ist die Cups-Version so alt, dass die Umgebungsvariable $DEVICE_URI nicht vorrangig als URI ausgewertet wird, sondern $0 :-(
    Ein Update ist nicht möglich. Ansonsten wäre es eh kein Problem.


    in Cups wird das Script übrigens mit folgendem Code aufgerufen

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

    The post was edited 2 times, last by pram ().

  • Hai nomml,


    wird Dein script von cups als command aufgerufen, oder willst Du cups aufrufen?


    Wenn es um Weiterreichung geht, brauchst Du $0 garnicht patchen.
    Du könntest das array kopieren und dann den ersten Eintrag austauschen. Dann ist das ein ganz normaler Variablen-Vorgang.


    Wenn Du aufgerufen wirst, wird argv[0] doch sicher $1 entsprechen - oder etwas nich?

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • ich wollte das Script in cups als Backend angeben.
    Das Script sollte dabei wiederum ein anderes Backend aufrufen und nebenbei die Daten abzweigen.


    im Wesentlichen schaut es so aus

    Shell-Script
    1. #!/bin/bash
    2. # Druckdaten wegkopieren
    3. cp $6 /tmp/Datenmitschnitt/
    4. ...
    5. export DEVICE_URI="socket://druckerIP:9100"
    6. # Druckdaten an das Socket-Backend weiterleiten
    7. ./socket $1 $2 $3 $4 $5 $6


    Das Script funktioniert auch unter neuerer Cups-Version, welche die DEVICE_URI und dann argv[0] auswertet. (Leider macht das die 1.1er noch anders)


    Ich schau jetzt mal ob ich das als Filter implementieren kann, weil ich an der Bash aufgegeben hab, da ich denke, dass es nicht geht.

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

  • Hallo pram,


    Ich habe mal einen flüchtigen Blick in cups1.1 geworfen und wenn ich nicht an der falschen Stelle gelandet bin, ist das, was Dir Kopfweh bereitet ist ein ganz normales array, welches "zufällig" argv heißt. Das könnte auch Hugo heißen und somit ist argv[0] einfach nur das erste Element und keineswegs geschützt.


    Wenn Du mal schaust, wo das array verwendet wird, steht dort

    Code
    1. pid = start_process(command, argv, envp, filterfds[!slot][0] ...

    bzw.


    Code
    1. execve(command, argv, envp);

    was bedeutet, dass Dein Scriptname in der Variablen command steht und nicht in argv[0].


    Dein Vorhaben sollte sich also realisieren lassen, ohne unanständig trixen zu müssen ;)


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Also wenn ICH Cups richtig durchschaut habe, wird in der job.c das Backend (z.B. Socket) aufgerufen.


    In der von dir erwähnten Codestelle wäre also:
    command = /usr/.../socket
    argv[0] = socket://ip:9100
    argv[1..n]... uninteressant


    Ich möchte jetzt "um" den Socket ein Wrapperscript basteln, damit ich die Daten abgreifen kann. Also ein einfaches Bash-Script. Die Device URI lautet dann z.B. socketwrapper://ip:port.


    anstatt "cupsJob->socket" sollte dann der Codepfad "cupsJob->socketwrapper->socket" lauten


    Variablenbelegung in Cups wäre dann:


    command = /usr/.../socketwrapper
    argv[0] = socketwrapper://ip:9100
    argv[1..n]... uninteressant


    Nun wird mein Wrapper-Script aufgerufen, dies schnappt sich die Daten und ruft dann das eigentliche socket-Backend auf.


    in der 1.1er steht zum Parsen der URI folgendes

    Code
    1. /*
    2. * Extract the hostname and port number from the URI...
    3. */
    4. httpSeparate(argv[0], method, username, hostname, &port, resource);


    hier wird die URI eben in argv[0] erwartet. Ich rufe aber das Backend aus meinem Bash-skript auf, somit steht da der Name des Backends drin.
    Ab der 1.2er machen sie das etwas intelligenter, was mir aber nicht viel hilft an dieser Stelle:

    Code
    1. /*
    2. * 'cupsBackendDeviceURI()' - Get the device URI for a backend.
    3. *
    4. * The "argv" argument is the argv argument passed to main(). This
    5. * function returns the device URI passed in the DEVICE_URI environment
    6. * variable or the device URI passed in argv[0], whichever is found
    7. * first.
    8. *
    9. * @since CUPS 1.2/Mac OS X 10.5@
    10. */


    -> Ich werd mir wohl oder übel einen Plan-B überlegen müssen .-(

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

  • Ich glaube dein Problem liegt im Dateisystem selbst. Ich vermute, dass argv[0] sowieso immer die aktuelle Datei ist und du somit gar keinen Einfluss darauf hast, es sei denn du machst einen Node-Eintrag ins Dateisystem. Und nur das kannst du an Cups weiterleiten. Daher mein Vorschlag: machs doch mit named pipes, die gibts auch in Bash. Die schreiben einen I-Node auf die Festplatte, so dass sie wie eine gültige Datei aussehen und dann rufst du cups mit diesem Pipe auf. Sobald das Lesen der Datei beendet ist, wird der Node wieder gelöscht und deine Platte ist sauber. Was hältst du davon?


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Quote

    In der von dir erwähnten Codestelle wäre also:
    command = /usr/.../socket
    argv[0] = socket://ip:9100
    argv[1..n]... uninteressant


    Ich möchte jetzt "um" den Socket ein Wrapperscript basteln, damit ich die Daten abgreifen kann. Also ein einfaches Bash-Script. Die Device URI lautet dann z.B. socketwrapper://ip:port.


    Also ich gehe man davon aus, dass /usr/.../socket eine ausführbare Datei ist, um die Du Deinen Wrapper legen willst. Wenn Dein Script mit verschiedenen "command"s arbeiten kann, dann würde ich das wrapperscript symlinken, sodass für jedes original-Command ein anderer Dateiname zu tragen komme ($0 in Deinem Script).


    Aus dem $0 kannst Du dann ablesen, welches Command wirklich aufgerufen werden soll.


    Ich gehe weiterhin davon aus, dass socket://... eine Protokollart, bzw. ein mime-Typ ist. Solange Du also keine Protokollart, bzw. keinen Mimetyp implementierst, wird es socketwrapper:// nicht geben. Du musst also Deinen Dienst so konfigurieren:
    command = /usr/.../socketwrapper
    argv[0] = socket://ip:9100


    In Deinem Wrapperscript wertest Du dann $0 aus und verwendest den Wert (z.B. basename) als Trigger für den Dienst, den dann Dein Script aufruft. Somit rufst Du den eigentlichen Service aus Deinem Script auf - und nur so wäre es ein richtiger Wrapper. Das was Du bisher vorgeschlagen hattest war das "man in the middle"-Prinzip und das geht natürlich nicht ohne cups zu patchen.


    Falls cups aus dem URL das command extrahiert und command und argv[0] mit dem gleichen Wert belegt, müsstest Du eben in Deinem Wrapperscript $1 (also den URI) auch patchen. Beides sollte machbar sein.


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Ihr versteht mich glaub ich nicht richtig. :deppenalarm


    Mein Wrapperscript funktioniert "perfekt", hier kann ich jeden Parameter auswerten usw usf.


    Ich kann nur nicht das gewrappede Backend (=socket) aufrufen, da in der


    int main(int argc, char *argv[])


    des (vorkonfiguriertem und für mich nicht änderbaren) Backends in argv[0] eben NICHT der Name des Programms, sondern die Device-URI erwartet wird.


    Ich habe aber jetzt folgendes gefunden: http://www.pykota.com/software/tea4cups
    Das ist eigentlich genau das was ich brauche, hier wird das folgendermaßen gemacht:

    Code
    1. originalbackend = os.path.join(os.path.split(sys.argv[0])[0], self.RealBackend)
    2. arguments = [os.environ["DEVICE_URI"]] + sys.argv[1:]
    3. ...
    4. os.execve(originalbackend, arguments, os.environ)


    Ich hoff jetzt mal, dass auf dem "Problemserver" python installiert ist...


    Gruß
    Roland

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

  • Yo,


    darfst mich ruhig als Depp ansehen - habe auch nie Dein Script oder Dein Wissen über Cups in Frage gestellt.


    Für mich geht es "nur" um die Problemstellung von $0 - und da denke ich auch, dass wir aneinander vorbei reden. Du willst $0 in Deinem Script verändern und ich wollte Dir klarmachen, dass das garnicht notwendig ist, denn das, was bei cups argv[0] ist, ist in Deinem Script $1


    ... und in dem codeschnippsel wird genau das gemacht, was ich Dir in meinem letzten Beitrag vorgeschlagen hatte. Dort wird nämlich auch der Pfad aufgetrennt, wieder neu zusammen gebaut und anschließend ein Befehl aufgerufen.


    Das geht genauso auch mit Bash oder was immer Du nehmen willst.


    Die Krux ist doch, dass Du wissen musst, was Du auswerten willst und woher Du Dein Ziel bekommst. Wenn Du dafür ne Environment-Variable nehmen willst, spricht ja nix dagegen.


    Wenn Du allerdings die Daten eines Socket abgreifen willst, ohne das Programm (cups) oder dessen Konfiguration zu ändern, dann würde es mich sehr beruhigen, wenn Du damit nicht (!) erfolgreich würdest.
    Schließlich gilt eine Socket-Verbindung als rel. sicher - und einen Wrapper einzubringen, ohne das cups was mitbekommt, würde die Sicherheit ad absurdum führen. So zumindest meine Ansicht!


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Quote

    Originally posted by pram
    Ich hoff jetzt mal, dass auf dem "Problemserver" python installiert ist...


    noe, ich glaub da tut's auch nen K&R-style C :lachen3



    du kannst dem 'fixarg0' als erstes Argument irgendwas Beliebiges geben, was dann fuer das aufgerufene prog als *(argv + 0)) erscheint.


    Beispiel:

    Code
    1. fixarg0 http://www.vdr-portal.de/ printmyargs arg1 arg2 arg3 ...


    Code
    1. *(argv + 0): http://www.vdr-portal.de/
    2. *(argv + 1): arg1
    3. *(argv + 2): arg2
  • geronimo , sry, der :deppenalarm war nicht auf dich bezogen. (Hätte besser den :doof Smiley verwenden sollen...)
    Evtl war auch meine Fragestellung nicht ganz klar, Sparkie scheints aber jetzt verstanden zu haben :)


    Zu deinen Bedenken: Die Cups-Konfiguration wird geändert. Die Device-URI lautet z.B. dann
    tea4cups://socket://1.2.3.4:9100



    Da Tea4Cups meine Anforderungen eigentlich erfüllen sollte, werde ich hier mal einen Versuch starten. Falls es kein python gibt (Der Server ist leider ne Marke Uralt...) dann muss wohl C herhalten...
    (Was mir sowieso besser gefallen würde...)


    Gruß
    Roland

    Software: VDR 1.4.3, mp3, osdpip, streamdev-server, femon, wapd, X11, Wireless Keyboard Kernel: 2.6.18
    Hardware: 1x DVB-S v 1.3, 1x Skystar 2, Celeron@2GHz, 256 MB RAM, 4 HDs Raid1/5, Total: 600 GB, Asus P4S533 cmi8738 & LAN on board 6 PCI
    40" Sammelbestellungs-LCD an ATI Radeon 9550 DVI-Out + tvtime, 70 cm TV an J2-RGB-Out
    Organisator der ersten und zweiten VDR-Sanitizer Sammelbestellung.
    In progress: POV-ION 330 - MediaPointer MP-S2 - vdr 1.7.9 - vdr-xine(vdpau)

  • Quote

    Originally posted by pram
    Falls es kein python gibt (Der Server ist leider ne Marke Uralt...) dann muss wohl C herhalten...


    also dieses neumodische objektorientierte Zeug wie C++ oder python - ich weiss ja nicht...


    plain C ist doch immer noch das Beste :lol2

  • Moin, moin,


    Quote

    geronimo , sry, ...


    Paßt schon! - Ich habe weder von cups ne Ahnung, noch wüsste ich, ob und wo man z.B. tea4Cups als Resource-Protokoll anmelden muss.


    Aber ich kann C und bash und soweit ich es verstanden habe, ist das, was sparkie Dir vorschlägt, locker auch mit bash möglich:
    fixarg.sh

    Shell-Script
    1. #!/bin/bash
    2. $2 $1 [$3 ... $9]


    ... das was ich Dir rüberbringen wollte, hat Sparkie mit seinen Codezeilen komprimiert:
    Dein Problem hängt nicht am $0, oder daran, dass Du $0 verändern müsstest, sondern daran, dass Du die URI bzw. Deinen $0 parsen solltest ...


    Quote

    tea4cups://socket://1.2.3.4:9100


    Hm - Ich weiß jetzt nicht, ob das ein gültiger URI ist. Wahrscheinlich müsste es ohne socket:// auskommen, bzw. nach socket müsste ein anderer Trenner kommen.


    Wenn Du Dein Script als Wrapper einbringen wolltest, würde ich statt socket://... das wrapperSocket:// verwenden. In dem wrapperSocket-Skript könnte man dann $0 aufteilen in "wrapper" und "Socket", bei "Socket" den ersten Buchstaben wieder kleinmachen und könnte dann aus dem wrapperSocket-Skript ein socket:// aufrufen.
    Die Behandlung des "neuen" URIs sollte also problemlos im Skript machbar sein.


    Wenn Du dann neben dem socket:// auch ein file:// wrappen wolltest, könntest Du einen Softlink wrapperFile auf wrapperSocket machen. Somit wäre das wrapperSocket-Skript schon generisch für 2 verschiedene URIs tauglich.


    Der Punkt ist nur, ich weiß nicht, was Du tun must, damit ein wrapperSocket://... als URI von cups akzeptiert wird.


    Also wenn Du schon soweit bist, dass Dein Skript von Cups aufgerufen werden kann, dann mach doch mal einen Test ala:

    Shell-Script
    1. #!/bin/sh
    2. echo "myself: $0"
    3. for i in $*; do
    4. echo "arg: $i";
    5. done


    Vielleicht ist es ja einfacher, wenn Du die Parameter vor Dir siehst. Die Ausgabe ist einfach zu deuten - myself ist $0 und jede Zeile ist fortlaufend zu nummerieren. Wenn Du dann in den Ausgaben siehst, aus welchen Parametern Du den neuen Befehl zusammen stellen willst, brauchst Du nur die entsprechenden Werte aufführen:

    Code
    1. $2 $1 $3


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!