GNU/Linux >> Tutoriels Linux >  >> Linux

shebang ou pas shebang

Au lieu d'avoir myprg détecter par magie s'il est utilisé dans un shebang, pourquoi ne pas le rendre explicite en utilisant un indicateur de ligne de commande (tel que -f ) pour lui passer un fichier en tant que script ?

De votre exemple dans les commentaires :

Dans l'exemple théorique calc ci-dessus. calc PI + 1 devrait retourner 4.14159... Maintenant, ajouter le support pour le shebang (c'est-à-dire un nom de fichier comme premier paramètre) renverrait le calcul contenu dans le fichier.

Faire calc prendre un fichier de script à travers -f puis créez des scripts avec :

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

Disons que vous appelez ce fichier addone.calc et le rendre exécutable. Ensuite, vous pouvez l'appeler avec :

$ ./addone.calc PI
4.141592...

Cet appel se traduira par une invocation de /usr/local/bin/calc -f ./addone.calc PI , il est donc assez clair quel argument est un fichier de script et lequel est un paramètre du script.

Ceci est similaire à la façon dont awk et sed se comporte.

Une approche similaire (mais opposée) consiste à avoir calc prendre un argument de fichier de script par défaut (ce qui simplifie son utilisation avec un shebang), mais ajouter un indicateur de ligne de commande pour l'utiliser avec une expression à partir d'un argument. Ceci est similaire à la façon dont sh -c '...' fonctionne.


Le vrai problème est la façon dont vous avez conçu la syntaxe de ligne de commande de <mypgm> . Au lieu d'essayer de soutenir deux manières d'interpréter ses arguments, proposez plutôt deux manières de l'appeler.

Les commandes Shebang sont censées être des moteurs de script qui exécutent le contenu de votre script; il peut s'agir de bash , perl , ou autre, mais on s'attend à ce qu'il soit appelé avec le nom de fichier d'un script à exécuter. Comment bash fais le? Il ne devine pas. S'il rencontre un argument qui ne ressemble pas à une option (ou à l'argument d'une option), il le traite comme le script à exécuter; les arguments suivants sont passés au script. Par exemple :

/bin/bash -x -e somename foo bar

Ici, bash cherchera le fichier somename et essayez de l'exécuter en tant que script avec les arguments foo et bar . Vous devriez faire la même chose, car vous pourriez veux écrire <mypgm> <myscript> sur la ligne de commande un jour.

Si vous voulez l'utilisation sans script de <mypgm> pour être la valeur par défaut, vous pouvez exiger qu'un script soit passé avec <mypgm> -f <myscript> . C'est ainsi que sed le fait. Ensuite, vous l'utiliseriez dans une ligne de shebang comme celle-ci :

#!<mypgm> -f

Si vous voulez que la casse du script soit la valeur par défaut, comme avec bash et perl , créez une option indiquant "il n'y a pas de script cette fois". Vous pouvez utiliser -- pour cela, de sorte que <mypgm> -- one two three n'essaie pas d'exécuter one (ou toute autre chose) en tant que script. Dans ce cas, la ligne shebang se lirait simplement :

#!<mypgm>

Maintenant, j'ai besoin de savoir quand blabla est appelé en utilisant le shebang, ou non :

En C, vous pouvez obtenir ces informations via getauxval(AT_EXECFN) , qui vous indiquera le nom de l'exécutable d'origine (c'est-à-dire le premier argument passé à execve(2) ) [1].

Mais cette chaîne est placée dans la mémoire immédiatement après les arguments de ligne de commande et les chaînes d'environnement, à la fin du [stack] région mémoire, afin qu'il puisse être récupéré directement à partir de là.

Par exemple, le script perl suivant (nommez-le foo.pl ), si rendu exécutable avec chmod 755 foo.pl , imprimera ./foo.pl lorsqu'il est exécuté directement et /usr/bin/perl lorsqu'il est exécuté en tant que 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";

Sur les noyaux Linux plus récents (>=3.5), la fin de l'environnement est également disponible dans /proc/PID/stat (dans le 51ème champ, comme documenté dans le proc(5) page de manuel).

#! /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] Les noyaux Linux plus récents que 2.6.26 ont introduit l'entrée de vecteur aux pointant dessus (voir le commit), mais le nom de l'exécutable était disponible à la fin de la pile bien avant cela (depuis linux-2.0 de 1996).


Linux
  1. Un script Bash peut-il être accroché à un fichier ?

  2. nano :commande introuvable

  3. tri :commande introuvable

  4. sed :commande introuvable

  5. La ligne shebang Ubuntu Python ne fonctionne pas

35 exemples de scripts bash

fsck :commande introuvable

queue :commande introuvable

toucher :commande introuvable

nohup :commande introuvable

fichier de création atomique s'il n'existe pas à partir du script bash