GNU/Linux >> Tutoriales Linux >  >> Linux

shebang o no shebang

En lugar de tener myprg detectar mágicamente si se está utilizando en un shebang, ¿por qué no hacerlo explícito mediante el uso de un indicador de línea de comandos (como -f ) para pasarle un archivo como script?

De su ejemplo en los comentarios:

En el ejemplo teórico de cálculo anterior. calc PI + 1 debería devolver 4.14159... Ahora agregar el soporte para shebang (es decir, un nombre de archivo como primer parámetro) devolvería el cálculo contenido en el archivo.

Hacer calc tomar un archivo de script a través de -f y luego crea scripts con:

#!/usr/local/bin/calc -f
$1 + 1

Digamos que llamas a este archivo addone.calc y hacerlo ejecutable. Entonces puedes llamarlo con:

$ ./addone.calc PI
4.141592...

Esa llamada se traducirá en una invocación de /usr/local/bin/calc -f ./addone.calc PI , por lo que está bastante claro qué argumento es un archivo de secuencia de comandos y cuál es un parámetro para la secuencia de comandos.

Esto es similar a cómo awk y sed se comporta.

Un enfoque similar (pero opuesto) es tener calc tome un argumento de archivo de secuencia de comandos de forma predeterminada (lo que simplifica su uso con un shebang), pero agregue un indicador de línea de comando para usarlo con una expresión de un argumento. Esto es similar a cómo sh -c '...' funciona.


El problema real es la forma en que diseñó la sintaxis de la línea de comandos de <mypgm> . En lugar de tratar de respaldar dos formas de interpretar sus argumentos, proporcione dos formas de llamarlo.

Los comandos Shebang están destinados a ser motores de secuencias de comandos que ejecutan el contenido de su secuencia de comandos; podría ser bash , perl , o lo que sea, pero la expectativa es que se llame con el nombre de archivo de un script para ejecutar. ¿Cómo bash ¿hazlo? No adivina. Si encuentra algún argumento que no parece una opción (o el argumento de una opción), lo trata como el script a ejecutar; los argumentos posteriores se pasan al script. Por ejemplo:

/bin/bash -x -e somename foo bar

Aquí, bash buscará el archivo somename e intente ejecutarlo como un script con argumentos foo y bar . Deberías hacer lo mismo, porque podrías quiero escribir <mypgm> <myscript> en la línea de comando algún día.

Si desea el uso sin secuencias de comandos de <mypgm> para que sea el valor predeterminado, puede solicitar que se pase un script con <mypgm> -f <myscript> . Así es como sed lo hace. Entonces lo usarías en una línea shebang como esta:

#!<mypgm> -f

Si desea que el caso del script sea el predeterminado, como con bash y perl , cree una opción que diga "esta vez no hay guión". Podrías usar -- para esto, para que <mypgm> -- one two three no intenta ejecutar one (o cualquier otra cosa) como un guión. En ese caso, la línea shebang simplemente diría:

#!<mypgm>

Ahora, necesito saber cuándo se llama blabla usando shebang o no:

En C, puede obtener esa información a través de getauxval(AT_EXECFN) , que le indicará el nombre del ejecutable original (es decir, el primer argumento pasado a execve(2) ) [1].

Pero esa cadena se coloca en la memoria inmediatamente después de los argumentos de la línea de comando y las cadenas de entorno, al final de [stack] región de memoria, por lo que se puede obtener directamente desde allí.

Por ejemplo, el siguiente script perl (nómbrelo foo.pl ), si se hace ejecutable con chmod 755 foo.pl , imprimirá ./foo.pl cuando se ejecuta directamente y /usr/bin/perl cuando se ejecuta como perl ./foo.pl :

#! /usr/bin/perl

open my $maps, "/proc/self/maps" or die "open /proc/self/maps: $!";
my $se;
while(<$maps>){ $se = hex($1), last if /^\w+-(\w+).*\[stack\]$/ }
open my $mem, "/proc/self/mem" or die "open /proc/self/mem: $!";
sysseek $mem, $se - 512, 0;
sysread $mem, $d, 512 or die "sysread: $!";
print $d =~ /([^\0]+)\0+$/, "\n";

En los núcleos de Linux más nuevos (>=3.5), el final del entorno también está disponible en /proc/PID/stat (en el campo 51, como se documenta en el proc(5) página de manual).

#! /usr/bin/perl

open my $sh, "/proc/self/stat" or die "open /proc/self/stat: $!";
my @s = <$sh> =~ /\(.*\)|\S+/g;
open my $mem, "/proc/self/mem" or die "open /proc/self/mem: $!";
seek $mem, $s[50], 0;
$/ = "\0";
my $pn = <$mem> or die "readline: $!"; chomp $pn; print "$pn\n";

[1] Los núcleos de Linux más nuevos que 2.6.26 introdujeron la entrada de vector auxiliar que apuntaba a él (consulte la confirmación), pero el nombre del ejecutable estaba disponible al final de la pila mucho antes (desde linux-2.0 de 1996).


Linux
  1. ¿Se puede conectar un script Bash a un archivo?

  2. dos2unix:comando no encontrado

  3. chmod:comando no encontrado

  4. mkfs:comando no encontrado

  5. archivo:comando no encontrado

35 ejemplos de secuencias de comandos Bash

ordenar:comando no encontrado

sed:comando no encontrado

archivo de creación atómica si no existe desde el script bash

La línea Shebang de Ubuntu Python no funciona

El script SH en $PATH no se encuentra en Linux Alpine 3.11