GNU/Linux >> Linux Esercitazione >  >> Linux

shebang o non shebang

Invece di avere myprg rilevare magicamente se viene utilizzato in uno shebang, perché non renderlo esplicito utilizzando un flag della riga di comando (come -f ) per passargli un file come script?

Dal tuo esempio nei commenti:

Nell'esempio teorico di calcolo sopra. calc PI + 1 dovrebbe restituire 4.14159... Ora aggiungendo il supporto per lo shebang (cioè un nome file come primo parametro) restituirebbe il calcolo contenuto nel file.

Crea calc prendi un file di script attraverso -f e quindi creare script con:

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

Diciamo che chiami questo file addone.calc e renderlo eseguibile. Quindi puoi chiamarlo con:

$ ./addone.calc PI
4.141592...

Quella chiamata si tradurrà in un'invocazione di /usr/local/bin/calc -f ./addone.calc PI , quindi è abbastanza chiaro quale argomento è un file di script e quale è un parametro dello script.

Questo è simile a come awk e sed si comporta.

Un approccio simile (ma opposto) è avere calc accetta un argomento del file di script per impostazione predefinita (che ne semplifica l'uso con uno shebang), ma aggiungi un flag della riga di comando per usarlo con un'espressione da un argomento. Questo è simile a come sh -c '...' funziona.


Il vero problema è il modo in cui hai progettato la sintassi della riga di comando di <mypgm> . Invece di cercare di supportare due modi di interpretare i suoi argomenti, fornisci invece due modi di chiamarlo.

I comandi Shebang sono pensati per essere motori di script che eseguono il contenuto del tuo script; potrebbe essere bash , perl , o qualsiasi altra cosa, ma l'aspettativa è che venga chiamato con il nome file di uno script da eseguire. Come funziona bash fallo? Non indovina. Se incontra un argomento che non sembra un'opzione (o l'argomento di un'opzione), lo tratta come lo script da eseguire; gli argomenti successivi vengono passati allo script. Ad esempio:

/bin/bash -x -e somename foo bar

Qui, bash cercherà il file somename e prova a eseguirlo come uno script con argomenti foo e bar . Dovresti fare la stessa cosa, perché potresti vuoi scrivere <mypgm> <myscript> un giorno sulla riga di comando.

Se vuoi l'uso senza script di <mypgm> per essere l'impostazione predefinita, puoi richiedere che uno script venga passato con <mypgm> -f <myscript> . Ecco come sed lo fa. Quindi lo useresti in una riga shebang come questa:

#!<mypgm> -f

Se vuoi che lo script case sia l'impostazione predefinita, come con bash e perl , crea un'opzione che dica "questa volta non ci sono script". Potresti usare -- per questo, in modo che <mypgm> -- one two three non tenta di eseguire one (o qualsiasi altra cosa) come sceneggiatura. In tal caso la riga shebang leggerebbe semplicemente:

#!<mypgm>

Ora, ho bisogno di sapere quando blabla viene chiamato usando lo shebang, oppure no:

In C, puoi ottenere queste informazioni tramite getauxval(AT_EXECFN) , che ti dirà il nome dell'eseguibile originale (cioè il primo argomento passato a execve(2) ) [1].

Ma quella stringa viene inserita nella memoria immediatamente dopo gli argomenti della riga di comando e le stringhe di ambiente, alla fine del [stack] regione di memoria, in modo che possa essere recuperato direttamente da lì.

Ad esempio, il seguente script perl (chiamalo foo.pl ), se reso eseguibile con chmod 755 foo.pl , stamperà ./foo.pl quando eseguito direttamente e /usr/bin/perl quando eseguito come 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";

Sui kernel Linux più recenti (>=3.5) la fine dell'ambiente è disponibile anche in /proc/PID/stat (nel 51° campo, come documentato nel proc(5) manpage).

#! /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] I kernel Linux più recenti di 2.6.26 hanno introdotto la voce del vettore aux che punta ad esso (vedi il commit), ma il nome dell'eseguibile era disponibile alla fine dello stack molto prima (da linux-2.0 del 1996).


Linux
  1. Script della shell:condizione "se il file non viene utilizzato"?

  2. dos2unix:comando non trovato

  3. nano:comando non trovato

  4. chmod:comando non trovato

  5. ordina:comando non trovato

35 Esempi di script Bash

coda:comando non trovato

tocco:comando non trovato

nohup:comando non trovato

file di creazione atomico se non esiste dallo script bash

La linea di Ubuntu Python shebang non funziona