Místo myprg
magicky detekovat, zda se používá v shebang, proč to neudělat explicitně pomocí příznaku příkazového řádku (například -f
) předat soubor jako skript?
Z vašeho příkladu v komentářích:
V teoretickém příkladu výpočtu výše.
calc PI + 1
by měl vrátit 4.14159... Nyní přidání podpory pro shebang (tj. název souboru jako první parametr) by vrátilo výpočet obsažený v souboru.
Vytvořte calc
proveďte soubor skriptu přes -f
a poté vytvořte skripty pomocí:
#!/usr/local/bin/calc -f
$1 + 1
Řekněme, že tento soubor nazýváte addone.calc
a učinit jej spustitelným. Poté jej můžete zavolat pomocí:
$ ./addone.calc PI
4.141592...
Toto volání se přeloží do vyvolání /usr/local/bin/calc -f ./addone.calc PI
, takže je celkem jasné, který argument je soubor skriptu a který parametr skriptu.
Je to podobné jako awk
a sed
se chová.
Podobný (ale opačný) přístup je mít calc
vezměte ve výchozím nastavení argument souboru skriptu (což zjednodušuje jeho použití s shebang), ale přidejte příznak příkazového řádku, abyste jej mohli použít s výrazem z argumentu. Je to podobné jako sh -c '...'
funguje.
Skutečným problémem je způsob, jakým jste navrhli syntaxi příkazového řádku <mypgm>
. Namísto toho, abyste se snažili podporovat dva způsoby interpretace jeho argumentů, poskytněte místo toho dva způsoby jeho volání.
Příkazy Shebang jsou určeny jako skriptovací stroje, které spouštějí obsah vašeho skriptu; může to být bash
, perl
, nebo cokoliv jiného, ale očekává se, že bude volána s názvem souboru skriptu, který se má spustit. Jak funguje bash
Udělej to? To nehádá. Pokud narazí na nějaký argument, který nevypadá jako volba (nebo argument volby), považuje jej za skript, který se má provést; argumenty poté jsou předány skriptu. Například:
/bin/bash -x -e somename foo bar
Zde bude bash hledat soubor somename
a zkuste jej spustit jako skript s argumenty foo
a bar
. Měli byste udělat totéž, protože můžete chcete napsat <mypgm> <myscript>
jednoho dne na příkazovém řádku.
Pokud chcete použít <mypgm>
bez použití skriptů Chcete-li být výchozí, můžete vyžadovat, aby byl skript předán s <mypgm> -f <myscript>
. Takto je sed
to dělá. Pak byste jej použili v řádce Shebang, jako je tento:
#!<mypgm> -f
Pokud chcete, aby velikost písmen skriptu byla výchozí, jako u bash
a perl
, vytvořte možnost, která říká „tentokrát není žádný skript“. Můžete použít --
za to, že <mypgm> -- one two three
se nepokouší spustit one
(nebo cokoli jiného) jako scénář. V takovém případě by řádek shebang zněl:
#!<mypgm>
Teď potřebuji vědět, kdy se blabla nazývá pomocí shebang nebo ne:
V C můžete tyto informace získat pomocí getauxval(AT_EXECFN)
, který vám řekne název původního spustitelného souboru (tj. první argument předaný do execve(2)
) [1].
Tento řetězec je však umístěn do paměti bezprostředně za argumenty příkazového řádku a řetězce prostředí, na konec [stack]
paměťovou oblast, takže ji lze načíst přímo odtud.
Například následující skript perl (pojmenujte jej foo.pl
), pokud je proveden jako spustitelný s chmod 755 foo.pl
, vytiskne ./foo.pl
při přímém spuštění a /usr/bin/perl
při spuštění jako 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";
Na novějších (>=3.5) linuxových jádrech je konec prostředí dostupný také v /proc/PID/stat
(v 51. poli, jak je uvedeno v proc(5)
manuálová stránka).
#! /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] Linuxová jádra novější než 2.6.26 zavedla položku aux vector, která na ni ukazovala (viz potvrzení), ale název spustitelného souboru byl k dispozici na konci zásobníku dlouho předtím (od linuxu-2.0 z roku 1996).