2012-05-08 13 views
8

Primero, ya busqué en Google pero solo encontré ejemplos donde un archivo comprimido (digamos un .tar.gz) está incrustado en un script de shell.Incrustar un ejecutable binario en un script de shell

Básicamente si tengo un programa C (hello.c) que imprime una cadena, digamos ¡Hola, mundo!.

que compilarla para obtener un binario ejecutable

gcc hello.c -o hello 

Ahora tengo un script de shell testEmbed.sh

Lo que estoy preguntando es si es posible incrustar el binario (hola) dentro de la shell script de manera que cuando corro

./testEmbed.sh 

se ejecuta el binario para imprimir ¡Hola, mundo!.

aclaración: Una alternativa es comprimir el ejecutable en un archivo y luego extraerlo cuando se ejecuta el script. Lo que estoy preguntando es si es posible ejecutar el programa sin eso.

Hasta ahora, estaba probando el método here. Pero no funciona para mí. Supongo que el autor estaba usando otra distribución en otra arquitectura. Entonces, básicamente, esto no funcionó para mí. : P

Además, si el flujo de trabajo para un programa C difiere de un Java jar, ¡me gustaría saberlo también!

Respuesta

14

Sí, esto se puede hacer. En realidad, es bastante similar en concepto a su artículo vinculado. El truco es usar uuencode para codificar el binario en formato de texto y luego virarlo al final de su script.

Su secuencia de comandos se escribe de tal manera que ejecuta uudecode en sí mismo para crear un archivo binario, cambiar los permisos y luego ejecutarlo.

uuencode y uudecode se crearon originalmente para cambiar el contenido binario en el precursor de internet, que no manejaba bien la información binaria. La conversión en texto significa que también se puede enviar como un script de shell. Si, por alguna razón, su distribución se queja cuando intenta ejecutar uuencode, probablemente signifique que debe instalarlo. Por ejemplo, en Debian Squeeze:

sudo aptitude install sharutils 

obtendrá los archivos ejecutables relevantes para usted. Este es el proceso por el que pasé. En primer lugar crear y compilar el programa C hello.c:

pax> cat hello.c 

#include <stdio.h> 
int main (void) { 
    printf ("Hello\n"); 
    return 0; 
} 

pax> gcc -o hello hello.c 

A continuación, cree un script de shell testEmbed.sh, que se descodificarlo en:

pax> cat testEmbed.sh 

#!/bin/bash 
rm -f hello 
uudecode $0 
./hello 
rm -f hello 
exit 

La primera rm declaración demuestra que el ejecutable hello está siendo creado de nuevo por esta secuencia de comandos, no se queda fuera de su compilación.Ya que se necesita la carga útil en el archivo, así, adjuntar el archivo ejecutable codificada al final de la misma:

pax> uuencode hello hello >>testEmbed.sh 

Posteriormente, cuando se ejecuta la secuencia de comandos testEmbed.sh, extrae el ejecutable y lo ejecuta.

La razón por la que esto funciona es porque uudecode busca ciertas líneas de marcador en su entrada (begin y end) que se ponen allí por uuencode, por lo que sólo intenta descodificar el programa codificado, no toda la secuencia de comandos:

pax> cat testEmbed.sh 

#!/bin/bash 
rm -f hello 
uudecode $0 
./hello 
rm -f hello 
exit 

begin 755 hello 
M?T5,[email protected]$!`0````````````(``P`!````$(,$"#0```#`[email protected]```````#0`(``' 
M`"@`'@`;``8````T````-(`$"#2`!`[email protected]````X`````4````$`````P```!0! 
: : : 
M:&%N9&QE`%]?1%1/4E]%3D1?7P!?7VQI8F-?8W-U7VEN:70`7U]B<W-?<W1A 
M<G0`7V5N9`!P=71S0$!'3$E"0U\R+C``7V5D871A`%]?:38X-BYG971?<&-? 
4=&AU;[email protected]`;6%I;@!?:6YI=``` 
` 
end 

Hay otras cosas de las que probablemente debería preocuparse, como la posibilidad de que su programa requiera bibliotecas compartidas que no existen en el sistema de destino, pero el proceso anterior es básicamente lo que necesita.


El proceso para un archivo JAR es muy similar, excepto que la forma de ejecutarlo es diferente. Es todavía un solo archivo, pero es necesario para reemplazar la línea:

./hello 

con algo capaz de ejecutar archivos JAR, tales como:

java -jar hello.jar 
+2

También podría ser una buena idea agregar un 'trap 'rm -f hello' SIGINT' al script del shell para que el archivo temporal se limpie en caso de que el usuario Ctrl-C sea el programa. –

+0

Sí, no dudo de que haya una gran cantidad de mejoras que pueda hacer en ese código y que _es_ una buena. No quiero complicarlo demasiado, ya que solo intento transmitir el concepto. – paxdiablo

+0

Una muy buena explicación. Gracias – Ankit

2

La forma portátil para hacer esto es con el comando printf y octal escapa:

printf '\001\002\003' 

para imprimir bytes 1, 2 y 3. Puesto que es probable que no quiere escribir que todo a mano, el comando od -b se puede utilizar para generar un volcado octal del archivo, luego puede usar un script sed para quitar la basura y colocar las barras invertidas correctas en su lugar.

+0

El comando para crear el string con los octals es 'od - b BINARYFILE | sed -n 's% [0-9] \ {4, \} \ \ ([0-9] \ {3 \}. * \)% \ 1% p' | perl -pe 's% ^% \\%; s% \% \\% g; s% \ n %% ') '. Esta cadena octal creada es la que debe tener' printf' como argumento. – erik

Cuestiones relacionadas