Wie stabil sind die „stdin/stdout-APIs“ der Unix-Shell?

Wie stabil sind die „stdin/stdout-APIs“ der Unix-Shell?

grepping, awking, sedding und piping gehören zur täglichen Routine eines Benutzers eines Unix-ähnlichen Betriebssystems, sei es auf der Kommandozeile oder in einem Shell-Skript (gemeinsam genanntFiltervon jetzt an).

Im Wesentlichen, wenn man mit "Standard" Unix CLI-Programmen und Shell-Builtins (kollektiv genannt) arbeitetBefehleVon nun an benötigen Filter ein genaues erwartetes Format für stdin, stdout und stderr in jedem Filterschritt, um korrekt zu funktionieren. Dieses genaue erwartete Format eines Befehls nenne ich im Folgenden eine API dieses Befehls.

Als jemand mit Webentwicklungshintergrund vergleiche ich diese Art der Datenerfassung und -verarbeitung technisch mitWeb Scraping- eine Technik, die bei der geringsten Änderung in der Datenpräsentation sehr instabil ist.

Meine Frage bezieht sich nun auf die Stabilität von Unix-Befehls-APIs.

  1. Unterliegen Befehle in Unix-ähnlichen Betriebssystemen hinsichtlich ihrer Eingabe und Ausgabe einer formalen Standardisierung?
  2. Gab es in der Vergangenheit Fälle, in denen Aktualisierungen eines wichtigen Befehls dazu führten, dass die Funktionalität eines Filters, der mit einer älteren Version des besagten Befehls erstellt wurde, beeinträchtigt wurde?
  3. Sind Unix-Befehle mit der Zeit so ausgereift, dass es absolut unmöglich ist, sie so zu ändern, dass irgendein Filter kaputt gehen könnte?
  4. Falls Filter aufgrund sich ändernder Befehls-APIs von Zeit zu Zeit kaputt gehen können, wie kann ich als Entwickler meine Filter vor diesem Problem schützen?

Antwort1

Der POSIX 2008-Standard enthält einen Abschnitt, der beschreibt"Shell und Dienstprogramme". Wenn Sie sich daran halten, sollten Ihre Skripte im Allgemeinen relativ zukunftssicher sein, mit Ausnahme möglicher Veralterungen. Diese passieren jedoch kaum über Nacht, sodass Sie genügend Zeit haben sollten, Ihre Skripte zu aktualisieren.

In einigen Fällen, in denen das Ausgabeformat für ein einzelnes Dienstprogramm je nach Plattform und Version stark variiert, kann der POSIX-Standard eine Option enthalten, die normalerweise -poder genannt wird und -Pein garantiertes und vorhersehbares Ausgabeformat angibt. Ein Beispiel hierfür ist dietimeDienstprogramm, das sehr unterschiedliche Implementierungen hat. Wenn Sie ein stabiles API/Ausgabeformat benötigen, verwenden Sie time -p.

Wenn Sie ein Filterdienstprogramm verwenden müssen, das nicht vom POSIX-Standard abgedeckt wird, sind Sie weitgehend auf die Gnade der Distributionspaketierer/Upstream-Entwickler angewiesen, genauso wie Sie beim Web Scraping auf die Gnade der Remote-Webentwickler angewiesen sind.

Antwort2

Ich werde versuchen, aus meiner Erfahrung zu antworten.

  1. Befehle unterliegen nicht wirklich einer formalen Spezifikation, sie unterliegen jedoch der Anforderung, zeilenorientierten Text zu verarbeiten und zu generieren.

  2. Ja, natürlich. Bevor die GNU-Dienstprogramme zum De-facto-Standard wurden, hatten viele Anbieter eigenartige Ausgaben, insbesondere in Bezug auf psund ls. Das hat viel Ärger verursacht. Heute liefert nur noch HP extrem eigenartige Befehle. Historisch gesehen waren die Dienstprogramme der Berkeley Software Distribution (BSD) ein großer Bruch mit der Vergangenheit. Die POSIX-Spezifikation war ein Bruch mit der Vergangenheit, wird aber mittlerweile allgemein akzeptiert.

  3. Unix-Befehle sind im Laufe der Zeit tatsächlich ausgereifter geworden. Es ist immer noch nicht unmöglich, ein für eine ältere Version geschriebenes Skript zu beschädigen. Denken Sie an den jüngsten Trend zu UTF-8 als Textdateikodierung. Diese Änderung machte Änderungen an grundlegenden Dienstprogrammen wie erforderlich tr. In der Vergangenheit war einfacher Text fast immer ASCII (oder etwas Ähnliches), sodass Großbuchstaben ebenso wie Kleinbuchstaben einen numerischen Bereich bildeten. Dies gilt bei UTF-8 nicht mehr, sodass trverschiedene Befehlszeilenoptionen akzeptiert werden, um Dinge wie „Großbuchstaben“ oder „alphanumerisch“ anzugeben.

  4. Eine der besten Möglichkeiten, Ihre Filter robuster zu machen, besteht darin, sich nicht auf ein bestimmtes Textlayout zu verlassen. Verwenden Sie beispielsweise nicht cut -c10-24, das von den Positionen einer Zeile abhängt. Verwenden Sie cut -f2stattdessen , wodurch das zweite, durch Tabulatoren getrennte Feld entfernt wird. awkunterteilt jede Eingabezeile in $1, $2, $3..., die standardmäßig durch Leerzeichen getrennt sind. Verlassen Sie sich auf Konzepte höherer Ebene wie „Felder“ statt auf Konzepte niedrigerer Ebene wie die Spaltenposition. Verwenden Sie außerdem reguläre Ausdrücke: sedund awkkönnen beide Dinge mit regulären Ausdrücken tun, die sich nicht um Abweichungen in der Eingabe scheren. Ein weiterer Trick besteht darin, die Eingabe in etwas zu verarbeiten, dessen Format Ihr Filter wählerisch sein kann. Verwenden Sie , tr -cs '[a-zA-z0-9]' '[\n]'um Text in ein einzelnes Wort pro Zeile ohne Satzzeichen aufzuteilen. In diesem Fall ist Ihnen der Eingabetext einfach egal.

Antwort3

Zunächst ganz kurze Antworten auf Ihre Fragen:

  1. Formale Standardisierung von Eingabe-/Ausgabekonventionen:NEIN
  2. Bruch in der Vergangenheit durch Leistungsänderung:Ja
  3. Es ist absolut unmöglich, zukünftige Filter zu beschädigen:NEIN
  4. Wie kann ich mich vor Änderungen schützen:konservativ sein

Wenn Sie „API“ sagen, verwenden Sie einen Begriff, der (ob gut oder schlecht) zu viel Formalität in Bezug auf Filter-Eingabe-/Ausgabekonventionen impliziert. Sehr (und ich meine „sehr“) allgemein sind die primären Konventionen für Daten, die sich leicht filtern lassen,

  • jede Eingabezeile ist ein vollständiger Datensatz
  • Innerhalb jedes Datensatzes werden die Felder durch ein bekanntes Trennzeichen getrennt

Ein klassisches Beispiel wäre das Format von /etc/passwd. Diese Standardkonventionen werden jedoch wahrscheinlich häufiger verletzt als strikt befolgt.

  • Es gibt viele Filter (oft in awk oder Perl geschrieben), die mehrzeilige Eingabeformate analysieren.
  • Es gibt viele Eingabemuster (z. B. /var/log/messages), bei denen keine klar definierte Feldstruktur vorliegt und allgemeinere, auf regulären Ausdrücken basierende Techniken verwendet werden müssen.

Ihre vierte Frage, wie Sie sich vor Abweichungen in der Ausgabestruktur schützen können, ist eigentlich die einzige, gegen die Sie etwas tun können.

  • Als@jw013 sagte, schauen Sie sich an, was die POSIX-Standards sagen. Natürlich gibt POSIX nicht alle Befehle an, die Sie als Eingabequellen verwenden möchten.
  • Wenn Sie möchten, dass Ihre Skripte portierbar sind, versuchen Sie, die Eigenheiten der jeweiligen Version des Befehls zu vermeiden, den Sie gerade installiert haben. Beispielsweise haben viele GNU-Versionen von Standard-Unix-Befehlen nicht standardmäßige Erweiterungen. Diese können nützlich sein, aber Sie sollten sie vermeiden, wenn Sie maximale Portabilität wünschen.
  • Versuchen Sie herauszufinden, welche Teilmengen von Befehlsargumenten und Ausgabeformaten plattformübergreifend stabil sind. Leider erfordert dies den Zugriff auf mehrere Plattformen und Zeit, da diese Unterschiede nicht einmal informell schriftlich festgehalten werden.

Letztendlich können Sie sich nicht vollständig vor den Problemen schützen, die Sie beunruhigen, und es gibt keine einzige Stelle, an der Sie nach einer „definitiven“ Aussage darüber suchen können, was ein bestimmter Befehl tun soll. Für viele Shell-Skripte, insbesondere solche, die für den persönlichen oder kleinen Gebrauch geschrieben wurden, ist dies einfach kein Problem.

Antwort4

Es gibt nur De-facto-IO-Standards – durch Leerzeichen und Nullen getrennte Ausgabe.

Was die Kompatibilität betrifft, greifen wir normalerweise auf die Überprüfung der Versionsnummern einzelner Filter zurück. Nicht, dass sie sich viel ändern würden, aber wenn Sie eine brandneue Funktion verwenden möchten und das Skript trotzdem auf älteren Versionen laufen soll, müssen Sie es irgendwie per „ifdef“ herausnehmen. Es gibt praktisch keinen Mechanismus zur Fähigkeitsberichterstattung, außer dem manuellen Schreiben von Testfällen.

verwandte Informationen