On Tue, Aug 02, 2022 at 05:51:40PM +0200, Arno wrote:
Am 02.08.22 um 07:15 schrieb tomas(a)tuxteam.de:
> On Mon, Aug 01, 2022 at 05:17:25PM +0200, Arno wrote:
> > Beim booten läuft bei mir ein script. Gestartet aus einem rc5.d/Sxx.
> > [...] Soweit so normal.
[...]
Das ist alles
halb so wild. Shell ist shell. Du musst wissen, mit welcher
Du es zu tun hast (ist es die bash? ist es ihre kleine Schwester) und
Ja, es ist nur die /bin/sh
"die" /bin/sh gibt es nicht wirklich:
tomas@trotzki:~$ ls -al /bin/sh
lrwxrwxrwx 1 root root 4 Dec 10 2020 /bin/sh -> dash
(Wenn Du sagst, dass es bei Dir eine Busybox ist, dann wird's etwas
anders sein).
das einzige, was dieser Tage erwartet wird ist, dass sie einigermassen
Bourne-kompatibel ist.
> Du musst berücksichtigen, mit welcher Umgebung Du
es zu tun hast (ist
> $PATH so wie Du sie erwartest? [...]
Das ist klar, da verwende ich nur absolute Pfade.
Nicht so klar: vielleicht willst Du Deinen Anwender*innen einen "Platz"
geben für "hier was auch immer Ihr für rm benutzt". Die OO-Fuzzis nennen
sowas "mixin". Man kann den Kopf so oder auch so drehen :-)
Zusatzfrage:
Wenn ein Script wie meines gerade aus Funktionen besteht:
Am Ende der Funktionsdefinitionen werden die aufgerufen.
Kann man z.B. zum Testen, diese Funktionen (aus einer echten) Shell auch
einzeln aufrufen?
How do the masters do it?
Einen netten Ansatz findest Du bei den alten sysvinit-Skripten. Die
ersten zwei Zeilen (abgesehen von Kommentaren) in einem (Quizfrage:
welches?) von meinen sehen so aus:
[ -r /usr/share/postgresql-common/init.d-functions ] || exit 0
. /usr/share/postgresql-common/init.d-functions
Es wird eine Datei "gesourct", in der irgendwelche nützliche Funktionen
definiert werden. Das würde ich mal das "library"-Pattern nennen.
Konkret: Wenn value=10 vor dem Aufruf von init.d-functions steht, dann
ist value dort bekannt.
Aber was wenn ich in init.d-functions value2=20 setze.
Kann ich die 20 in dem aufrufenden Vater-Script verwenden?
Nicht in einem "Unterskript". Aber in einer Funktion. Die Frage ist,
ob Du das /willst/. Du siehst Deinem Hauptskript nicht an, ob eine
Variable zwei Stockwerke tiefer verändert wird. Vielleicht passiert
das nur aus Versehen, weil jemand "da unten" auch den Namen $BLUNTSCHLI
für was ganz anderes verwendet wurde?
Entweder machst Du dazu also Gebrauch vom Library-Pattern (s.o.), oder
Du "gibst ein Ergebnis zurück". Da strenggenommen Shell-Funktionen nur
eine Art (Integer) "Fehlercode" zurückliefern, kannst Du mit stdout
arbeiten:
secret-name () {
echo "rumpelstilzchen"
}
SECRET=$(secret-name)
... so etwas funktioniert. Auch noch krasser:
SECRET=$(secret-name | sed -e s/u/ü/g)
Das schöne an dem Stil ist, dass Du in Deinem Hauptprogramm /siehst/,
dass der Wert der Variable SECRET verändert wird.
[...]
Nehmen wir an,
ich habe ein Skript, nennen wir es "muuh":
#!/bin/bash
echo "Guten Morgen"
say-hello ()
{
echo hello
}
say-good-bye ()
{
echo good bye
}
Und dann "source" ich das Ding in einem anderen:
...
. muuh
...
Ok aber kann ich auch (Syntax frei erfunden)
. muh::say-hello()
machen und dann wird nur "hello" zurückgebeben.
Das meine ich, wenn ich die Funktionen eines Scripts testen will.
Nö, sowas wie namespaces gibt es nicht.
Bei mir wäre gegenwärtig das Problem das das muh wohl
so aussieht:
#/bin/sh
funk1() { echo 1 }
funk2() { echo 2 }
funk3() { echo 3 }
echo Test
funk1
echo blabla
funk3
funk2
Ich müsste zum Test die unteren 5 Zeilen komplett rausnehmen und
source muh.sh
funk2
machen um nur funk2 zu testen, richtig?
(Syntax-Anmerkung: nach "echo 1" usw muss wahrscheinlich ein ; sein)
Richtig. Der erste Stück geht in eine eigene Datei, my-functions, der
zweite benutzt das. Das ist vermutlich die "lesbarste" Variante. Nicht
die einzige. Eine andere:
#!/bin/sh
# datei: muh
fun1 () { ... }
...
if [ -n "$TESTING" ] ; then exit 0 ; fi
echo blabla
Also: wenn die Variable TESTING gesetzt ist, dann hüpfst Du raus,
nachdem die Funktionen definiert wurden aber bevor der Schaden
angerichtet ist. Mir gefällt die Variante nicht so sehr, aber sie
soll ja Dir gefallen :-)
Was passiert
ist, dass wenn die Ausführung in meinem Skript an diesen
Punkt kommt, "Guten Morgen" ausgegeben wird (wohin immer gerade stdout
zeigt) und die zwei Funktionen definiert werden, die ich dann im
weiteren Verlauf verwenden kann.
Immerhin. Also sind die Funktionen auch nach Ausführung noch verfügbar.
Ja, im Skript immer.
> Ein ganz gerader, naiver Interpreter: mach'
dies, dann mach' das [...]
Also vielen Dank für die Mühe, dann werd ich mich mal
ans refactoring
machen und mit kleinen Demos beginnen.
Gerne :)
lg
--
t