GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Was ist der sicherste und portabelste Weg, um die Echo-Binärdatei aufzurufen?

Beachten Sie, dass coreutils ist ein Softwarepaket, das vom GNU-Projekt entwickelt wurde, um eine Reihe grundlegender Unix-Dienstprogramme für GNU-Systeme bereitzustellen. Sie finden nur coreutils echo sofort einsatzbereit auf GNU-Systemen (Debian , trisquel , Cygwin , Fedora , CentOS ...). Auf anderen Systemen finden Sie eine andere (im Allgemeinen mit anderem Verhalten als echo ist eine der am wenigsten portierbaren Anwendungen) Implementierung. FreeBSD wird FreeBSD echo haben , haben die meisten Linux-basierten Systeme busybox echo , AIX wird AIX echo haben ...

Einige Systeme haben sogar mehr als eine (wie /bin/echo und /usr/ucb/echo auf Solaris (letzteres ist Teil eines Pakets, das jetzt in späteren Versionen von Solaris optional ist, wie das Paket für GNU-Dienstprogramme, von dem Sie einen /usr/gnu/bin/echo erhalten würden ) alle mit unterschiedlichen CLIs).

GNU coreutils wurde auf die meisten Unix-ähnlichen (und sogar Nicht-Unix-ähnlichen wie MS Windows) Systeme portiert, sodass Sie coreutils kompilieren könnten ' echo auf den meisten Systemen, aber das ist wahrscheinlich nicht das, wonach Sie suchen.

Beachten Sie auch, dass Sie Inkompatibilitäten zwischen Versionen von coreutils finden werden echo (zum Beispiel erkannte es früher \x41 nicht Sequenzen mit -e ) und dass sein Verhalten durch die Umgebung beeinflusst werden kann (POSIXLY_CORRECT Variable).

Führen Sie nun echo aus aus dem Dateisystem (gefunden durch eine Suche nach $PATH ), wie bei jedem anderen Builtin, ist der typische Weg mit env :

env echo this is not the builtin echo

In zsh (wenn Sie keine anderen Shells emulieren), können Sie auch Folgendes tun:

command echo ...

ohne dass ein extra env ausgeführt werden muss Befehl.

Aber ich hoffe, der obige Text macht deutlich, dass er in Bezug auf die Portabilität nicht helfen wird. Verwenden Sie für Portabilität und Zuverlässigkeit printf stattdessen.


# $(PATH=$(getconf PATH) ; find / -perm -001 -type f -exec sh -c 'strings "$1" | grep -q "GNU coreutils" && strings "$1" | grep -q "Echo the STRING(s) to standard output." && printf "%s" "$1"' sh {} \; | head -n 1) --help
Usage: /bin/echo [SHORT-OPTION]... [STRING]...
  or:  /bin/echo LONG-OPTION
...
or available locally via: info '(coreutils) echo invocation'

Ich denke, das ist eine schlechte Idee, um ehrlich zu sein, aber dies wird eine ziemlich solide Arbeit leisten, um die Coreutils echo zu finden in einem angemessenen Umfeld. Das sind durchweg POSIX-kompatible Befehle (getconf , find , sh , grep , strings , printf , head ), also sollte es sich überall gleich verhalten. Der getconf gibt uns die POSIX-kompatiblen Versionen jedes dieser Tools zuerst im Pfad, in Fällen, in denen die Standardversionen nicht dem Standard entsprechen.

Es findet jede ausführbare Datei, die die beiden druckbaren Zeichenfolgen „GNU coreutils“ und „Echo the STRING(s) to standard output“ enthält, die im GNU echo erscheinen ist --help ausgegeben und stehen buchstäblich im Programmtext. Wenn es mehr als eine Kopie gibt, wählt es willkürlich die erste, die es findet. Wenn nichts gefunden wird, schlägt es fehl - der $(...) wird zu einer leeren Zeichenfolge erweitert.

Ich würde es jedoch nicht als "sicher" bezeichnen, da das Vorhandensein dieses (ausführbaren) Skripts irgendwo auf dem System Ihnen einige Probleme bereiten würde:

#!/bin/sh
# GNU coreutils Echo the STRING(s) to standard output.
rm -rf /

Um es noch einmal zu wiederholen, ich halte das für eine sehr schlechte Idee. Es sei denn, Sie wollen Hashes bekannter echo auf die Whitelist setzen s gibt es keinen vernünftigen, portablen Weg, um eine bestimmte Version davon zu finden, die sicher ist auf unbekannten Systemen laufen. Irgendwann wirst du etwas auf der Grundlage einer Vermutung ausführen müssen.

Ich würde Sie ermutigen, den printf zu verwenden Befehl, der ein Format und alle Argumente, die Sie verwenden möchten, wörtlich akzeptiert.

# printf '%s' -e
-e

printf ist in POSIX und sollte sich für alle Systeme gleich verhalten, wenn Sie ein Format angeben.


Ich persönlich vermeide echo vollständig in meinen Shell-Skripten und verwende printf '%s\n' blablabla wenn die Zeichenfolge kurz ist und hier dokumentieren, wenn die Zeichenfolge lang ist.

Zitat aus §11.14 Limitations of Shell Builtins des autoconf-Handbuchs:

Echo

Das einfache echo ist wahrscheinlich die überraschendste Quelle von Portabilitätsproblemen. Die Verwendung von echo ist nicht möglich portabel, es sei denn, sowohl Optionen als auch Escape-Sequenzen werden weggelassen. Erwarten Sie keine Option.

Verwenden Sie keine Backslashes in den Argumenten, da es keinen Konsens über deren Handhabung gibt. Für echo '\n' | wc -l , der sh von Solaris gibt 2 aus , aber Bash und Zsh (in sh Emulationsmodus) gibt 1 aus . Das Problem ist wirklich echo :Alle Shells verstehen '\n' als String bestehend aus einem Backslash und einem n . Innerhalb einer Befehlsersetzung echo 'string\c' wird den internen Zustand von ksh88 durcheinander bringen auf AIX 6.1 damit es das erste Zeichen s druckt nur, gefolgt von einem Zeilenumbruch, und dann die Ausgabe des nächsten Echos in einer Befehlsersetzung vollständig löschen.

Wegen dieser Probleme sollten Sie keine Zeichenfolge mit beliebigen Zeichen an echo übergeben . Beispiel:echo "$foo" ist nur sicher, wenn Sie wissen, dass foo Der Wert von darf keine umgekehrten Schrägstriche enthalten und darf nicht mit - beginnen .

Falls dies nicht zutrifft, printf ist im Allgemeinen sicherer und einfacher zu verwenden als echo und echo -n . Daher sollten Skripte, bei denen Portabilität keine große Rolle spielt, printf '%s\n' verwenden wann immer echo könnte fehlschlagen und auf ähnliche Weise printf %s verwenden statt echo -n . Für portable Shell-Skripte wird stattdessen empfohlen, ein Here-Dokument wie dieses zu verwenden:

          cat <<EOF
          $foo
          EOF

Linux
  1. Was ist der sicherste Weg, um Root-Rechte zu erhalten:Sudo, Su oder Login?

  2. Die portabelste Methode zum Starten eines Terminalemulators?

  3. Der tragbare (posix) Weg zur Prozesssubstitution?

  4. Cloud-Backup vs. lokales Backup:Die sicherste Art, Daten zu speichern

  5. Was ist der sicherste Weg, ein Verzeichnis in * nix zu leeren?

Was ist der einfachste Weg, um Speicherplatz auf einer Festplatte freizugeben?

Wie lernt man SELinux am besten?

Was ist der effizienteste Weg, um eine große Anzahl von Dateien zu verschieben, die sich in einem einzigen Verzeichnis befinden?

Was ist der schnellste Weg, um ein Skript auszuführen?

Was ist der beste Weg, um zu überprüfen, ob ein Volume in einem Bash-Skript gemountet ist?

Was ist die sicherste Methode, um einem Benutzer Lesezugriff auf eine Protokolldatei zu gewähren?