[linux-l] POSIX und busybox (was: Subtilitäten von find und xargs)

Steffen Dettmer steffen at dett.de
Mo Nov 19 01:56:13 CET 2007


* Mike Dornberger wrote on Sat, Nov 17, 2007 at 04:20 +0100:
> Hi,
> 
> On Sat, Nov 17, 2007 at 01:12:13AM +0100, Steffen Dettmer wrote:
> > * Mike Dornberger wrote on Fri, Nov 16, 2007 at 02:23 +0100:
> > > > externes_Programm ist entweder POSIX und gut oder nicht und
> > > > durchgefallen - oder?
> > > 
> > > externes_Programm_macht_Ausgabe = (eines m)ein(r) Shellscript(e),
> > > "beliebige" Ausgabe per echo oder printf? *gnnna* Ich sehe schon, geht
> > > bestimmt wieder nicht ohne ein Beispiel:
> > 
> > ja, ich versteh wirklich kein Wort...
> 
> hm, reden wir vielleicht aneinander vorbei?

möglich...

> Ich bezog mich immer darauf, daß ich _Shell-Scripte_ schreiben will, deren
> Syntax (nach Möglichkeit) POSIX-konform ist (und die nicht zu aufgebläht
> sein sollen). Dazu zähle ich aber auch die Aufruf-Syntax von Programmen, die
> man in einer POSIX-konformen Umgebung typischerweise vorfindet. 

Ja, OK, das meinte ich auch. Dann kann Dein Script (genauer: Dein
"Programm", was "Unterprogramme" [find, ...] benutzt) natürlich nur
POSIX-konform sein, wenn es nur POSIX-konforme "Fremdprogramme" nutzt.
Das meinte ich mit "ssh-agent impliziert nicht-POSIX-konform", weil es
POSIX-konforme Systeme gibt, auf denen kein ssh-agent ist und Dein
Script (Programm) nicht funktionieren wird (weil es ja von ssh-agent
abhängt).

Mein Ursprungspunkt war ja, ob man das nicht pragmatisch machen sollte,
also z.B. "meine Platform hat eben XYZ", oder "wenn man XYZ nicht hat,
braucht man das nicht" oder "dann geht es eben nicht" oder gar "wenn man
XYZ *will* hat man meist auch ABC". Letzeres wäre z.B. "wenn man ein
Installationsprogramm für Direct4D für Linux ausführt, hat man X. Also
kann es eine GUI nutzen", auch wenn das nicht POSIX ist. Es könnte sogar
Linux-spezifisch sein. Natürlich könnte man es sonst theoretisch unter
BSD (Windows, ...) nutzen, aber wozu? Also muss man es nicht
ermöglichen, oder?

> (Ich glaube, dazu sagt die OpenGroup.org auch was, aber ich hab gerade
> keinen Browser zur Hand um das rauszusuchen.) Zu diesen Programmen
> zählen zum Beispiel echo, test, sed, printf, ggf. find.

Genau, aber nicht ssh-agent...

> Natürlich rufen meine von mir geschriebenen (und meist noch nicht
> veröffentlichten) Scripte in der Regel auch "externe" Programme, wie
> z. B.  rsync, auf.
> 
> Mir geht es darum, daß ich mir durch praktische Übung bewußt mache, was
> POSIX ist und was nicht und wo ich nachschauen kann, wenn ich mir nicht
> sicher bin, etc. pp.

Na ja gut, ist mir schon klar, das hab ich verstanden. Mir ging es ja
aber darum, ob das wirklich immer gut ist. Wenn z.B. ein Script dreimal
so gross, fünfmal so fehlerträchtig und zehnmal so langsam wird, wenn
ich POSIX-konform sein muss, dieses Script aber nur unter SuSE Linux
laufen soll, kann es doch bash benutzen (hat SuSE ja). Vielleicht
kann/soll/möchte man nicht immer blind "POSIX für alles und jeden"
nehmen?

> > > Ich habe so ein Konstrukt neulich mal gebraucht um aus einer Datei
> > > (Liste von Verzeichnissen/Dateien, jeweils mit \n separiert), in einem
> > > Script ein find \( -path "./datei_dir1" -or -path "./datei_dir2*" \) und
> > > einem anderen Script ein rsync-Kommando zusammenzubauen, wobei für
> > > letzteres Spaces gequotet werden mußten.
> > 
> > (warum hier nicht einfach "rsync -r ./datei_dir[12]* ziel"?)
> > 
> > Datei mit Dateinamen? Kann man mit "read < file" einlesen, oder?
> 
> Warum muß ich mich jetzt vor dir verteidigen warum ich gewisse Dinge so
> mache? :) Na gut, noch eine kleine Erklärung.

Na ja, es ist schwer zu verstehen, wenn Du Beispiele bringst, die ich
auch nicht verstehe :)

Du willst POSIX-konform ein nicht-POSIX Programm starten. Ich frage,
warum Du es nicht einfach startest, weil das Programm bzw. die Shell das
meiner Meinung nach schon kann. In beiden Fällen seh ich keinen
Zusammenhang zu POSIX (ist es nicht). Daher hilft mir das Beispiel
nicht.

> Wenn du meinen Text oben nochmal liest, steht da was von 2 Scripten.
> Diese sind natürlich nicht vollständig unabhängig voneinander und
> gehören zum selben "Projekt". Wichtig ist halt, daß beide mit der
> _selben_ (sozusagen synchronen) Liste von Dateien/Verzeichnissen
> arbeiten müssen.

"./datei_dir[12]*" sollte in beiden das gleiche sein :) Sonst kann man
es in eine Datei schreiben klar. Wie und wozu auch immer. Aber was hat
das mit POSIX-Konformität zu tun? Ist es einfach nicht. Wegen rsync und
weil es für Dateien mit "\n" im Dateinamen nicht funktioniert (was POSIX
sicherlich erlaubt).

> > > Die Kommandos werden in einer Variablen zusammengebaut und
> > > anschließend eval "$Variable". 
> > 
> > (klingt gefährlich...)
> 
> Ja und? :)

Na ja, warum will man POSIX. Vielleicht, damit man Risiken vermeidet
(neuere Versionen, andere Systeme, irgendsowas). Aber wenn man dann eine
ganz komplizierte Lösung braucht, die gefährlich ist, hat man ja doch
keine Risiken vermieden. Daher würde man doch da überlegen sollen, nicht
lieber was einfaches zu machen. Wenn man das dann woanders braucht,
macht man es halt nochmal. Im rsync-Beispiel ist das gut zu sehen, was
ich meine. Man hat überhaupt kein Script, sondern ruft rsync einfach
auf. Hat man eine andere Shell, ruft man es trozdem auf (nur ggf. halt
anders).

Ist mir schon klar, dass das nicht immer funktioniert.

> muß man sich dann wieder wirklich viele Gedanken darum machen, wie man (den
> Namen) dieser Datei denn nun erzeugt, sodaß Sachen wie "symlink attacks"
> nicht möglich sind, udgl.

TMPFILE=`mktemp /tmp/$0.XXXXXX` || exit 1

gute Beispiel. Würde ich für Linux-Scripte nehmen. Geht dann auf POSIX
eventuell nicht, weil man mktemp nicht hat. FALLS man das jemals
braucht, kann man sich das ja als Funktion implementieren. Oder es muss
halt installiert sein. Letzeres führt natürlich schnell zu riesigen
Systemen, da muss man Grenzen ziehen, klar.

> Gut könnte man "für privat" ja alles weglassen und so, aber wie schon
> gesagt, geht es mir darum, Dinge zu üben und sich bewußt zu machen.

Prima! Genau darum geht es mir auch. Bewusst machen, ob (dass)
POSIX-konform nicht um jeden Preis will, sozusagen :)

> > > Oh, mir fällt noch ein einfacherer Fall ein, der tatsächlich auch
> > > große Relvanz hat: 'eval `ssh-agent`' und 'eval `ssh-agent -k`'
> > > 
> > > Und nun teste mal ein Script auf POSIX-konformität, daß irgendwo eval
> > > `ssh-agent -k` aufruft. 
> > 
> > Ist es nicht, weil ssh-agent muss ja gar nicht existieren.
> 
> Du hast keine Phantasie. ;) 

Wieso?! Das ganze ist doch dafür da, damit Dein Script in einer
POSIX-und-sonst-nichts-weiter funktioniert. Spielt aber doch hier keine
Rolle, es kann nicht funktionieren, weil ssh-agent nicht da ist. Daher
muss Dein Script überhaupt nicht auf allen POSIX Umgebungen laufen,
sondern nur auf denen, die ssh-agent haben. Pragmatisch gesehen kannst
Du dann auch "ssh-add -l" nutzen, weil vermutlich überall, wo ssh-agent
da ist, auch ssh-add da ist. Das ist natürlich keine Bedingung (man
könnte ja ein System mit ssh-agent aber ohne ssh-add machen, notfalls
mit rm :)), klar, aber ist es wichtig, dass *da* Dein Script noch
korrekt läuft? So ein System wirst Du wohl eh nie machen :)

> Stell dir doch einfach vor, ich möchte testen, ob meine .profile
> POSIX-konform ist und da hab ich halt eine Funktion definiert, die ich
> aufrufen kann, wenn ich einen bestimmten ssh-agent killen will. 

Mal unabhängig von POSIX:
Aber man möchte doch einen einzigen Agenten auf der ersten (sichersten)
Maschinen laufen haben und den nie killen? Warum hat man mehrere und
will auch noch einen davon killen?

> So, und nun, was passiert, wenn ich auf irgendeiner Konsole ein Script
> benutze, daß intensiv, in mehreren Aufrufen, diesen Agenten benutzt
> und ich nun den Tester anwerfe? Schwups, Agent weg und beim Script
> scheppert's.

Dann hängt Dein Script nicht von POSIX oder nicht POSIX ab, sondern auch
noch von dem Zustand von Agenten oder der Aufrufreihenfolge und dem
Wetter, was weiss ich :)

Dann lieber auf die Sachen mit Reihenfolgen und Wetter verzichten, auch
wenn es dann nicht mehr POSIX ist, aber dafür einfach nur funktioniert.
Du startest den agent ja nur da, wo er installiert ist, ergo musst Du
ihn auch nur da killen, demzufolge muss Dein Script nur da
funktionieren, wo ssh-agent da ist. Bei mir wäre das z.B. Linux aber
nicht OpenWRT. Da *ich* unter Linux immer ne Bash installiert hab,
könnte ich mit /bin/bash prima leben. Auf openWRT hab ich keine bash,
aber auch keinen agent, also stört mich da nix.

> > natürlich die Grenzen wieder fliessend, 
> 
> Naja, eigentlich wollte ich am Anfang der Diskussion mit meinem
> Einwurf nur sagen, daß so ein Testtool entweder wohl ziemlich schnell
> an seine Grenzen stößt oder halt Dinge im laufenden Betrieb einfach
> kaputt machen kann.

Ach so. Na gut, das Thema hatte ich nicht so verstanden.

Ja, es wird schnell an Grenzen stossen, weil die Laufzeit und
Daten-Komplexität zu ungünstig (schnell) wächst. Es würde sich bei
mini-Scripten schon totprüfen, fürchte ich.

Das Testtool würde natürlich nichts kaputt machen. Es müsste sowieso
eine Art "virtueller Umgebung" nutzen, beispielsweise, um zu prüfen, ob
POSIX-konforme Fehlermeldungen korrekt erkannt werden und so weiter.

Aber für eine pragmatische Prüfung (ich würde es "Ausprobieren",
"Versuch", "Experiment" oder so nennen; Prüfung ist systematisch und in
Richtung vollständig) wäre ein Prüfprogram denkbar. Beispielweise könnte
man den "Gutfall" ausprobieren. Das sagt natürlich nicht, ob es
POSIX-konform ist, sondern erstmal nur, dass es auch auf
POSIX-Umgebungen korrekt funktionieren /könnte/.

> > Wenns um Stabilität nach Updates geht, dann find ich sash gut.
> 
> Mit der hab ich mich noch nicht außeinandergesetzt. Vielleicht sollte man
> eher allgemein sagen: "Es gibt kleine Shells, die POSIX-konform sein wollen.

Ich glaube nicht, dass sash POSIX-konform sein will! Im Gegenteil, sash
ist das sicherlich verdammt egal. sash will maximale
Notfall-Funktionalität bieten, selbst wenn ld.so komplett gehimmelt ist.
das sash-find ist sicherlich sehr rudimentär, aber es ist viel besser,
als überhaupt kein find :)

> Teste dein Script doch mit denen mal." Was dann natürlich nur erstmal für
> die Syntax des Scripts gilt. Ob man sed, echo, printf, test, ... "richtig"
> verwendet, kann man dann wohl nur rausfinden, wenn man entweder statt der
> GNU-Tools was anderes verwendet oder eben wirklich in eine "native"
> Solaris- oder vielleicht BSD-Umgebung, beispielsweise. Oder eben halt die
> Seiten der OpenGroup.org studiert. :)

... oder man nimmt halt GNU-Tools. Dann läuft das Script auf'm
programmierbaren POSIX-Taschenrechner halt nicht.

Oder man nimmt gleich Perl. Mit paar echo/sed in Schleifen kriegt man
Shellscripte schnell tötlich langsam hin... Ist schliesslich immer ein
fork/exec!

> > Aber, funktioniert nicht? Was passiert dann? Sollte man doch hinkriegen.
> 
> Ich kenne den momentanen Stand der Diskussion um die Shell, auf die /bin/sh
> unter Debian standardmäßig zeigen soll, nicht. Aber wann immer jemand ein
> Script (in Debian-Paketen) findet, daß XSI- oder bash-Konstrukte benutzt und
> trotzdem "nur" /bin/sh als Interpreter angibt, soll er das natürlich melden.
> Solch ein Bug ist dann wohl Priority: serious oder sogar höher, da in der
> Debian-Policy eben steht, wenn /bin/sh, dann auch keine Spezial-Konstrukte.

Ahh ja, OK, das verstehe ich.
Ich finde, es ist ein Bug, wenn /bin/sh einen definieren Funktionsumfang
hat, die bash einen reduzierten Funktionsumfang bietet, wenn man sie als
/bin/sh aufruft *aber dann bash Spezifika vorhanden sind*. Sonst hätte
man das Problem gar nicht: bash und sonstwas würden sich gleich
verhalten, wenn man als /bin/sh aufruft und bash-Konstrukte würden zu
Fehlern führen.

Für den Fall klingt es nach einer guten Idee, eine einfache, kleine
Shell als /bin/sh zu verwenden. Man einigt sich sozusagen auf den
kleinsten gemeinsamen Nenner.


> > > Ich hatte das unter Sarge auch mal probiert, aber einige Wrapper, wie z.
> > > B. zless benutz(t)en Bash-Konstrukte, obwohl sie eine #!/bin/sh Zeile
> > > haben, sodaß ich wieder die bash als Link-Zeil von /bin/sh eingestellt
> > > hatte.
> > 
> > Versteh ich nicht. Wenn man ne einfachere, kleinere Shell nimmt, hat man
> > natürlich weniger Funktionalität, klar. Was hattest Du erwartet?
> 
> Es ging mir darum, daß diese Wrapper #!/bin/sh stehen haben und nicht
> #!/bin/bash, obwohl sie Bash-Konstrukte benutzen.

Ach so, ja klar, haste ja auch geschrieben :)
Ja, genau, zwei Bugs: zum einen, dass /bin/sh da steht und zum anderen,
dass es auch noch funktioniert, wenn man bash hat.

oki,

Steffen

-- 
Dieses Schreiben wurde maschinell erstellt,
es trägt daher weder Unterschrift noch Siegel.




Mehr Informationen über die Mailingliste linux-l