Wie finde ich den Unterschied zwischen einer Skriptdatei und einer Binärdatei?

11
$ ls -l /usr/bin
total 200732

-rwxr-xr-x 1 root   root     156344 Oct  4  2013 adb
-rwxr-xr-x 1 root   root       6123 Oct  8  2013 add-apt-repository
 list goes long ---------

Oben adbist eine Binärdatei und add-apt-repositoryeine Skriptdatei. Ich erhalte diese Informationen, indem ich die Dateien über nautilus ansehe. Aber über die Befehlszeile habe ich keine Unterschiede gefunden. Ich kann nicht vorhersagen, ob eine Datei eine Binärdatei ist oder nicht eine Skriptdatei.

Wie kann ich also über die Befehlszeile zwischen Skript- und Binärdateien unterscheiden?

Avinash Raj
quelle

Antworten:

16

Verwenden Sie einfach file:

$ file /usr/bin/add-apt-repository
/usr/bin/add-apt-repository: Python script, ASCII text executable
$ file /usr/bin/ab
/usr/bin/ab: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=569314a9c4458e72e4ac66cb043e9a1fdf0b55b7, stripped

Wie erklärt in man file:

NAME
   file — determine file type

DESCRIPTION
 This manual page documents version 5.14 of the file command.

 file tests each argument in an attempt to classify it.  There are three
 sets of tests, performed in this order: filesystem tests, magic tests,
 and language tests.  The first test that succeeds causes the file type to
 be printed.

 The type printed will usually contain one of the words text (the file
 contains only printing characters and a few common control characters and
 is probably safe to read on an ASCII terminal), executable (the file con‐
 tains the result of compiling a program in a form understandable to some
 UNIX kernel or another), or data meaning anything else (data is usually
 “binary” or non-printable).  Exceptions are well-known file formats (core
 files, tar archives) that are known to contain binary data.  When adding
 local definitions to /etc/magic, make sure to preserve these keywords.
 Users depend on knowing that all the readable files in a directory have
 the word “text” printed.  Don't do as Berkeley did and change “shell
 commands text” to “shell script”.

Sie können auch einen Trick verwenden, um dies direkt auf den Namen der ausführbaren Datei in Ihrem auszuführen $PATH:

$ file $(type -p add-apt-repository | awk '{print $NF}')
/usr/local/bin/add-apt-repository: Python script, ASCII text executable
$ file $(type -p ab | awk '{print $NF}')
/usr/bin/ab: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=569314a9c4458e72e4ac66cb043e9a1fdf0b55b7, stripped

So ermitteln Sie den Dateityp aller ausführbaren Dateien, die sich in Ihren Verzeichnissen $PATHbefinden:

find $(printf "$PATH" | sed 's/:/ /g') -type f | xargs file

Und um filealle Dateien in einem bestimmten Verzeichnis ( /usr/binzum Beispiel) auszuführen , tun Sie dies einfach

file /usr/bin/*
Terdon
quelle
Aber wir müssen filefür jede Datei ausführen, um zu sehen, um welchen Dateityp es sich handelt. Gibt es eine einfache Methode für alle Dateien?
Avinash Raj
3
@AvinashRaj für alle Dateien in einem bestimmten Verzeichnis? Tu es einfach file /usr/bin/*. Genau wie bei jedem anderen Befehl.
Terdon
5

Eigentlich sind die Unterschiede zwischen diesen nicht so groß.

Auf einem typischen Unix- oder Linux-System gibt es weniger als fünf echte ausführbare Dateien. Unter Ubuntu sind dies /lib/ld-linux.so.2und /sbin/ldconfig.

Alles andere, was als ausführbar markiert ist, wird über einen Interpreter ausgeführt , für den zwei Formate unterstützt werden:

  1. Dateien, die mit beginnen #!, haben den Interpreternamen zwischen diesem und dem ersten Zeilenumbruchzeichen (das ist richtig, es ist nicht erforderlich, dass "Skripte" Textdateien sind).
  2. ELF-Dateien haben ein PT_INTERPSegment, das (normalerweise /lib/ld-linux.so.2) den Pfad zum Interpreter angibt .

Wenn eine solche Datei ausgeführt wird, findet der Kernel den Namen des Interpreters und ruft ihn stattdessen auf. Dies kann rekursiv geschehen, beispielsweise wenn Sie ein Shell-Skript ausführen:

  1. Der Kernel öffnet das Skript und findet das #! /bin/sham Anfang.
  2. Der Kernel öffnet sich /bin/shund findet das PT_INTERPSegment, auf das er zeigt /lib/ld-linux.so.2.
  3. Der Kernel wird geöffnet /lib/ld-linux.so.2, stellt fest, dass er kein PT_INTERPSegment hat, lädt sein Textsegment und startet es, indem er das offene Handle an übergibt/bin/sh und die Befehlszeile für Ihren Skriptaufruf übergibt.
  4. ld-linux.so.2Lädt die Codesegmente aus /bin/sh, löst gemeinsam genutzte Bibliotheksreferenzen auf und startet die Hauptfunktion
  5. /bin/sh öffnet dann die Skriptdatei erneut und beginnt, sie Zeile für Zeile zu interpretieren.

Aus Sicht des Kernels besteht der einzige Unterschied darin, dass für die ELF-Datei der offene Dateideskriptor anstelle des Dateinamens übergeben wird. Dies ist meist eine Optimierung. Ob der Interpreter dann beschließt, zu einem aus der Datei geladenen Codesegment zu springen oder es Zeile für Zeile zu interpretieren, entscheidet nur der Interpreter und basiert hauptsächlich auf Konventionen.

Simon Richter
quelle
Gute Informationen, aber keine wirkliche Antwort auf diese Frage.
OrangeDog
Die Antwort ist Mu .
Simon Richter
1

Der Befehl file ist großartig, aber für ein professionelleres Analysetool möchte ich, dass Sie das TrID-Paket ausprobieren , bei dem es sich um ein Tool zur Dateikennung handelt.

TrID ist ein Dienstprogramm, mit dem Dateitypen anhand ihrer binären Signaturen identifiziert werden können. Es ist einfach zu verwenden.

Weitere Informationen und das Paket finden Sie unter: Site

nux
quelle