¿Cómo encontrar la diferencia entre un archivo de script y un archivo binario?

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

En lo anterior adbhay un archivo binario y add-apt-repositoryes un archivo de script. Obtengo esta información al ver los archivos a través de nautilus. Pero a través de la línea de comandos, no encontré ninguna diferencia. No puedo predecir si un archivo es binario o Un archivo de script.

Entonces, ¿cómo puedo diferenciar entre script y archivos binarios a través de la línea de comandos?

Avinash Raj
fuente

Respuestas:

16

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

Como se explica en 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”.

También puede usar un truco para ejecutar esto directamente en el nombre del ejecutable en su $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

Para encontrar el tipo de archivo de todos los ejecutables que se pueden encontrar en los directorios de su $PATH, puede hacer esto:

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

Y para ejecutar fileen todos los archivos en un directorio particular ( /usr/binpor ejemplo), simplemente haga

file /usr/bin/*
terdon
fuente
Pero tenemos que ejecutar filecada archivo para ver qué tipo de archivo es este. ¿Existe algún método simple para todos los archivos?
Avinash Raj
3
@AvinashRaj para todos los archivos en un directorio dado? Solo hazlo file /usr/bin/*. Como cualquier otro comando.
terdon
5

En realidad, las diferencias entre ellos no son tan grandes.

En un sistema Unix o Linux típico, hay menos de cinco ejecutables reales. En Ubuntu, estos son /lib/ld-linux.so.2y /sbin/ldconfig.

Todo lo demás marcado como ejecutable se ejecuta a través de un intérprete , para el cual se admiten dos formatos:

  1. Archivos que comienzan con #! tendrán el nombre del intérprete entre este y el primer carácter de nueva línea (es cierto, no es necesario que los "scripts" sean archivos de texto).
  2. Los archivos ELF tienen un PT_INTERPsegmento que proporciona la ruta al intérprete (generalmente/lib/ld-linux.so.2 ).

Cuando se ejecuta dicho archivo, el núcleo encuentra el nombre del intérprete y lo llama en su lugar. Esto puede suceder recursivamente, por ejemplo, cuando ejecuta un script de shell:

  1. El núcleo abre el script, encuentra el #! /bin/shal principio.
  2. El kernel se abre /bin/sh , encuentra el PT_INTERPsegmento que apunta /lib/ld-linux.so.2.
  3. El núcleo se abre /lib/ld-linux.so.2, encuentra que no tiene unPT_INTERP segmento, carga su segmento de texto y lo inicia, pasando el identificador abierto /bin/shy la línea de comando para la invocación de su script.
  4. ld-linux.so.2 carga los segmentos de código de /bin/sh , resuelve referencias de bibliotecas compartidas e inicia su función principal
  5. /bin/sh luego vuelve a abrir el archivo de script y comienza a interpretarlo línea por línea.

Desde el punto de vista del kernel, la única diferencia es que para el archivo ELF, se pasa el descriptor de archivo abierto en lugar del nombre del archivo; Esto es principalmente una optimización. Si el intérprete decide saltar a un segmento de código cargado desde el archivo, o interpretarlo línea por línea, solo lo decide el intérprete, y se basa principalmente en la convención.

Simon Richter
fuente
Buena información, pero no es realmente una respuesta a esta pregunta.
OrangeDog
La respuesta es Mu .
Simon Richter
1

Archivo comando de es excelente, pero para una herramienta de análisis más profesional, me gustaría que pruebe el paquete TrID, que es una herramienta de identificación de archivos.

TrID es una utilidad diseñada para identificar tipos de archivos a partir de sus firmas binarias, y es fácil de usar.

Para obtener más información y el paquete solo visite: Sitio

nux
fuente