Listen Sie alle Programme auf, die von einem Shell-Skript verwendet werden

7

Ich versuche eine Methode zu finden, um alle Programme aufzulisten, die ein Skript verwendet, wenn es ausgeführt wird, ohne es tatsächlich auszuführen.

Ich habe diese schnellen und schmutzigen Oneliner geschrieben:

# fill an array with all the useful words except variables, options, brackets, quotes
readarray -t list <<<$( grep -v '^#' script.sh | sed 's/[0-9a-zA-Z_\-]*=//g ; s/\${.*}//g ; s/\$(//g ; s/[)'\"\'\`']//g ; s/ --*.//g ' )

# for every word in array show info with `type' and clean the output again
for p in "${list[@]}" ; do type "${p}" ; done 2>&1 | grep -v -e '^bash:' -e 'shell keyword' -e 'shell builtin' | sort | uniq | sed 's/^.* //g ; s/[\(\)]//g'

Ich denke die Probleme sind:

  1. Wenn das Programm nicht installiert ist, schlägt "type" fehl
  2. Hier können Dokumente Schlüsselwörter enthalten, die Programme sein können ...
  3. Wenn das Skript nicht gut geschrieben ist, kann sich die Schwierigkeit erhöhen ("Shellcheck" kann nützlich sein).
  4. Externe Konfigurationsdateien und Funktionsbibliotheken werden nicht nachverfolgt (siehe ilkkachu-Kommentar).

Eine bessere Lösung?

Baselab
quelle
4
Führen Sie es unter straceund nehmen Sie alle exec()Anrufe zur Kenntnis ? Und dann versuchen Sie sicherzustellen, dass Sie alle möglichen Codepfade und alle möglichen Eingaben verarbeiten ... Ich glaube nicht, dass dies im Allgemeinen möglich ist, da alles, was das Skript tut, von externen Konfigurationsdateien und Funktionsbibliotheken usw.
abhängen kann
1
@ikkachu oderstrace -fe execve
Stéphane Chazelas
@ilkkachu, aber das bedeutet, dass das Skript tatsächlich ausgeführt wird und das OP es "ohne es tatsächlich auszuführen" ausführen muss.
Terdon
3
@baselab: Diese Art von Problemen ist im Allgemeinen unentscheidbar, daher gibt es keine Möglichkeit, sie genau zu lösen. Das Beste, was Sie tun können, ist ein heuristischer Ansatz - zum Beispiel das erste Wort in jeder Zeile zu sammeln und so zu tun, als wäre es ein externer Befehl -, aber es ist natürlich trivial, Fälle zu konstruieren, in denen Sie einen Befehl verpassen oder ein Wort als nehmen würden Befehl, der nicht ist. Und selbst wenn Sie das Programm tatsächlich ausführen (und stracewie vorgeschlagen verwenden), wird nur angezeigt, was in diesem bestimmten Lauf verwendet wurde. Andere Eingabedaten können dazu führen, dass andere Programme aufgerufen werden.
user1934428
Es würde auch Möglichkeiten geben, die Prüfung mit Aliasen auszutricksen und einige Umgebungsvariablen zu ändern ... Ich glaube nicht, dass es zuverlässig wäre, anhand der verwendeten Heuristiken zu prüfen ...
Zip

Antworten:

1

In Beitrag Nr. 16 des Threads https://www.unix.com/shell-programming-and-scripting/268856-how-pre-check-scrutinize-all-my-shell-scripts.html habe ich einen Perl mit 150 Zeilen gepostet Skript p1.txt , das ein nützlicher Ausgangspunkt sein kann. Ich habe auch einen Link zu einem weitaus vollständigeren, komplexeren Shell-Parser hinzugefügt

Es ist vielleicht am besten, den gesamten Thread zu betrachten - vielleicht sind auch einige andere Gesichtspunkte von Interesse.

Beste Grüße ... Prost, drl

drl
quelle
1
Danke für den Link und das Perl-Skript! Gestern habe ich angefangen, einen vollständigeren Parser zu schreiben, der auf meinen 2 Onelinern basiert. Ihre Links werden nützlich sein :)
Baselab
1
Bitte schön. Ich werde interessiert sein, was Sie sich einfallen lassen
,,, Prost
@baselab Ich würde mich auch dafür interessieren, was Sie sich
ausgedacht haben
0

Dies ist keine leichte Aufgabe. Sie haben bereits einige der Schwierigkeiten identifiziert. Textbasiertes Parsen ist sehr fehleranfällig, sehr einfach zu umgehen (wenn jemand möchte) und fast garantiert unvollständig.

Bash verfügt über eine integrierte 'Set'-Funktion, die das Skript analysiert, ohne es tatsächlich auszuführen. Dies könnte Ihnen helfen, aber auch das wird begrenzt sein.

  [set] -n      Read commands but do not execute them.  This may be used
                  to  check  a  shell  script  for syntax errors.  This is
                  ignored by interactive shells.

Um es in einem Skript zu testen, fügen Sie es einfach set -nam Anfang des Skripts hinzu und führen Sie es dann aus.

strace Dies ist sehr nützlich, erfordert jedoch, dass das Skript tatsächlich ausgeführt wird. Dies ist etwas, das Sie tun möchten, nachdem Sie sicher sind, dass das Skript sicher ist.

Pedro
quelle