Jak znaleźć różnicę między plikiem skryptu a plikiem binarnym?

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 ---------

Powyżej adbznajduje się plik binarny i plik add-apt-repositoryskryptu. Otrzymuję te informacje, przeglądając pliki za pomocą nautilus. Ale za pomocą wiersza polecenia nie znalazłem żadnych różnic. Nie jestem w stanie przewidzieć, czy plik jest plikiem binarnym lub plik skryptu.

Jak więc odróżnić pliki skryptu od plików binarnych za pomocą wiersza polecenia?

Avinash Raj
źródło

Odpowiedzi:

16

Po prostu użyj 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

Jak wyjaśniono w 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”.

Możesz także użyć lewy, aby uruchomić to bezpośrednio na nazwie pliku wykonywalnego w $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

Aby znaleźć typ pliku wszystkich plików wykonywalnych, które można znaleźć w swoich katalogach $PATH, możesz to zrobić:

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

Aby uruchomić filewszystkie pliki w określonym katalogu ( /usr/binna przykład), po prostu zrób

file /usr/bin/*
terdon
źródło
Ale musimy uruchomić filedla każdego pliku, aby zobaczyć, jaki to typ pliku. Czy istnieje jakaś prosta metoda dla wszystkich plików?
Avinash Raj
3
@AvinashRaj dla wszystkich plików w danym katalogu? Po prostu zrób file /usr/bin/*. Tak jak każde inne polecenie.
terdon
5

W rzeczywistości różnice między nimi nie są tak duże.

W typowym systemie Unix lub Linux istnieje mniej niż pięć prawdziwych plików wykonywalnych. W systemie Ubuntu są to /lib/ld-linux.so.2i /sbin/ldconfig.

Wszystko inne, co jest oznaczone jako wykonywalne, jest uruchamiane przez interpreter , dla którego obsługiwane są dwa formaty:

  1. Pliki zaczynające się od #!będą miały nazwę interpretera między tym a pierwszym znakiem nowego wiersza (to prawda, nie ma wymogu, aby „skrypty” były plikami tekstowymi).
  2. Pliki ELF mają PT_INTERPsegment, który podaje ścieżkę do interpretera (zwykle /lib/ld-linux.so.2).

Kiedy taki plik jest wykonywany, jądro znajduje nazwę interpretera i zamiast tego wywołuje go. Może się to zdarzyć rekurencyjnie, na przykład po uruchomieniu skryptu powłoki:

  1. Jądro otwiera skrypt, znajduje go #! /bin/shna początku.
  2. Jądro otwiera się /bin/shi znajduje PT_INTERPsegment wskazujący /lib/ld-linux.so.2.
  3. Jądro otwiera się /lib/ld-linux.so.2, stwierdza, że ​​nie ma PT_INTERPsegmentu, ładuje swój segment tekstowy i uruchamia go, przekazując otwarty uchwyt do /bin/shi wiersz poleceń do wywołania skryptu.
  4. ld-linux.so.2ładuje segmenty kodu /bin/sh, rozwiązuje odwołania do bibliotek współużytkowanych i uruchamia swoją główną funkcję
  5. /bin/sh następnie ponownie otwiera plik skryptu i zaczyna interpretować go wiersz po wierszu.

Z punktu widzenia jądra jedyną różnicą jest to, że w przypadku pliku ELF przekazywany jest deskryptor otwartego pliku, a nie nazwa pliku; jest to głównie optymalizacja. To, czy interpreter zdecyduje się następnie przejść do segmentu kodu załadowanego z pliku, czy zinterpretować go wiersz po wierszu, zależy wyłącznie od interpretera i głównie na podstawie konwencji.

Simon Richter
źródło
Dobra informacja, ale tak naprawdę nie jest odpowiedzią na to pytanie.
OrangeDog
Odpowiedź brzmi Mu .
Simon Richter
1

Polecenie pliku jest świetne, ale dla bardziej profesjonalnego narzędzia do analizy chciałbym wypróbować pakiet TrID, który jest narzędziem do identyfikacji plików.

TrID to narzędzie zaprojektowane do identyfikacji typów plików na podstawie ich podpisów binarnych i jest łatwe w użyciu.

Aby uzyskać więcej informacji i pakiet wystarczy odwiedzić: Witryna

nux
źródło