Tout d'abord, vous devriez très rarement utiliser $*
et vous devriez presque toujours utiliser "[email protected]"
à la place. Il y a un certain nombre de questions ici sur SO qui expliquent les tenants et les aboutissants de pourquoi.
Deuxième - la commande env
a deux utilisations principales. L'un est d'imprimer l'environnement actuel; l'autre est de contrôler complètement l'environnement d'une commande quand elle est exécutée. Le troisième usage, que vous démontrez, est de modifier l'environnement, mais franchement, il n'y a pas besoin de cela - les obus sont tout à fait capables de gérer cela pour vous.
Mode 1:
env
Mode 2:
env -i HOME=$HOME PATH=$PREPENDPATH:$PATH ... command args
Cette version annule toutes les variables d'environnement héritées et fonctionne command
avec précision l'environnement défini par les options ENVVAR = valeur.
Le troisième mode - modifier l'environnement - est moins important car vous pouvez le faire avec des coques régulières (civilisées). (. Cela signifie « pas shell C » - encore une fois, il y a d'autres questions sur SO avec des réponses qui expliquent que) Par exemple, vous pouvez parfaitement faire:
#!/bin/bash
export PATH=${PREPENDPATH:?}:$PATH
exec python "[email protected]"
Cette insiste sur le fait que $PREPENDPATH
est réglé sur un non chaîne vide dans l'environnement, puis l'ajoute à $PATH
et exporte le nouveau paramètre PATH. Puis, en utilisant ce nouveau PATH, il exécute le programme python
avec les arguments pertinents. Le exec
remplace le script shell par python
. Notez que ceci est assez différent de:
#!/bin/bash
PATH=${PREPENDPATH:?}:$PATH exec python "[email protected]"
Superficiellement, c'est pareil. Cependant, cela va exécuter le python
trouvé sur le PATH préexistant, mais avec la nouvelle valeur de PATH dans l'environnement du processus. Ainsi, dans l'exemple, vous finiriez par exécuter Python à partir de /usr/bin
et non de /home/pi/prepend/bin
.
Dans votre situation, je n'utiliserais probablement pas env
et j'utiliserais simplement une variante appropriée du script avec l'exportation explicite.
La commande env
est inhabituelle car elle ne reconnaît pas le double tiret pour séparer les options du reste de la commande. C'est en partie parce qu'il ne prend pas beaucoup d'options, et en partie parce qu'il n'est pas clair si les options ENVVAR = valeur devraient venir avant ou après le double tiret.
J'ai actuellement une série de scripts pour exécuter (différentes versions de) un serveur de base de données. Ces scripts utilisent vraiment env
(et un tas de programmes cultivés à domicile) pour contrôler l'environnement du serveur:
#!/bin/ksh
#
# @(#)$Id: boot.black_19.sh,v 1.3 2008/06/25 15:44:44 jleffler Exp $
#
# Boot server black_19 - IDS 11.50.FC1
IXD=/usr/informix/11.50.FC1
IXS=black_19
cd $IXD || exit 1
IXF=$IXD/do.not.start.$IXS
if [ -f $IXF ]
then
echo "$0: will not start server $IXS because file $IXF exists" 1>&2
exit 1
fi
ONINIT=$IXD/bin/oninit.$IXS
if [ ! -f $ONINIT ]
then ONINIT=$IXD/bin/oninit
fi
tmpdir=$IXD/tmp
DAEMONIZE=/work1/jleffler/bin/daemonize
stdout=$tmpdir/$IXS.stdout
stderr=$tmpdir/$IXS.stderr
if [ ! -d $tmpdir ]
then asroot -u informix -g informix -C -- mkdir -p $tmpdir
fi
# Specialized programs carried to extremes:
# * asroot sets UID and GID values and then executes
# * env, which sets the environment precisely and then executes
# * daemonize, which makes the process into a daemon and then executes
# * oninit, which is what we really wanted to run in the first place!
# NB: daemonize defaults stdin to /dev/null and could set umask but
# oninit dinks with it all the time so there is no real point.
# NB: daemonize should not be necessary, but oninit doesn't close its
# controlling terminal and therefore causes cron-jobs that restart
# it to hang, and interactive shells that started it to hang, and
# tracing programs.
# ??? Anyone want to integrate truss into this sequence?
asroot -u informix -g informix -C -a dbaao -a dbsso -- \
env -i HOME=$IXD \
INFORMIXDIR=$IXD \
INFORMIXSERVER=$IXS \
INFORMIXCONCSMCFG=$IXD/etc/concsm.$IXS \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG=onconfig.$IXS \
PATH=/usr/bin:$IXD/bin \
SHELL=/usr/bin/ksh \
TZ=UTC0 \
$DAEMONIZE -act -d $IXD -o $stdout -e $stderr -- \
$ONINIT "[email protected]"
case "$*" in
(*v*) track-oninit-v $stdout;;
esac
Cette information est utile, mais comme le dit OP, son/son noyau ne fonctionnera pas non les binaires (tels que les bouchons de bash que vous fournissez) comme premier élément d'une ligne shebang. La mienne non plus; plus précisément, le noyau ne parvient pas à exécuter le script avec la ligne shebang problématique dans l'interpréteur (non-binaire) souhaité, et mon shell va essayer d'exécuter le script à la place. (Ma compréhension est que c'est un comportement de coquille ancienne que beaucoup de coquilles retiennent.) – dubiousjim
Je ne comprends pas ce que vous dites? Voulez-vous dire qu'il y a (encore) des shells ou des noyaux qui ne gèreront pas #!/Bin/bash ou '#!/Bin/ksh' comme première ligne d'un script? Je ne prétends pas ou ne montre pas que vous pouvez utiliser '#!/Some/script' comme un shebang. –
Ne revendiquant pas le premier. La question de l'OP est à propos de la seconde, cependant: il/elle a demandé "Qu'est-ce que le noyau fait si vous collez un shell-script dans la ligne shebang?" puis signale les problèmes qui proviennent de l'utilisation d'env.1 comme une ligne shebang, où env.1 est un script. (En fait, il cherchait des discussions sur les limites des lignes de shebang qui m'ont amené ici.) J'ai trouvé que votre message avait des informations utiles, alors merci de l'avoir fait, je voulais juste le souligner, pour d'autres lecteurs qui viendront plus tard. que ce dont vous parlez n'aide pas à surmonter les limites auxquelles le PO s'est heurté.) – dubiousjim