J'ai écrit un script simple.
Quand j'ai exécuté sh <myscriptname.sh>
, j'ai eu le bon résultat, mais quand j'ai exécuté ./<myscriptname.sh>
, j'ai eu une erreur.
Quelle est la différence entre sh
et ./
?
Lorsque vous exécutez un script en transmettant le nom de fichier au programme d'interpréteur de script, vous exécutez le programme d'interprétation avec le script en tant qu'argument transmis. Par exemple, cela ressemblerait au processus 'sh' avec l'argument 'nomfichier.sh'. L'interpréteur sh
ouvre le fichier.
D'autre part, si vous exécutez le script lui-même, le système appelle le programme d'interpréteur spécifié et alimente le contenu des scripts. Dans ce cas, le processus ressemble à "filename.sh" sans arguments.
Vous devriez vous assurer que vous avez une ligne de bang:
#!/bin/bash
# bash script here
Une ligne de bang est la première ligne du script et commence par les deux mêmes caractères #!
, ce que le système lit lorsqu'il essaie d'exécuter le script, puis le système passe le script au programme immédiatement après. Notez que cette ligne n'a rien à voir avec bash et fonctionne aussi bien pour python que pour perl, même si les langages sont très différents. Vous utiliseriez #!/usr/bin/python
par exemple et vous suivriez ensuite avec du code python.
Une fois que vous avez votre script, assurez-vous d’avoir défini les droits d’exécution:
chmod a+x filename.sh
Ensuite, vous pouvez exécuter le script en tant que processus distinct:
./filename.sh
Ou placez le fichier dans un emplacement connu avec un nom de programme intéressant, tel que /usr/sbin
et exécuté de n'importe où:
sudo cp filename.sh /usr/sbin/program-name
program-name
Et c’est vraiment le avantage pratique d’utiliser la ligne bang avec les bonnes autorisations - tout ce qui concerne le déploiement . Il est très difficile d'inciter les utilisateurs à exécuter un script s'ils doivent se souvenir de quel programme exécuter le script. N'oubliez pas de donner un chemin complet au script chaque fois qu'il veut l'exécuter. Le fait de le placer dans /usr/local/bin
par exemple et de le rendre exécutable peut permettre d’éviter énormément de chagrin aux personnes qui essaient d’utiliser votre script. Ces programmes deviennent alors disponibles pour tous les utilisateurs de sur votre ordinateur.
C'est aussi bon pour l'identification. Si vous allez dans le programme top
, un script exécuté sans la ligne bang aura simplement le nom de l'interpréteur, c'est-à-dire bash
, perl
ou python
. Mais si un script est exécuté avec les bonnes autorisations, le nom du script s'affiche.
Remarque: Si vous souhaitez distribuer un script accessible à tous, créez une page de manuel et un package deb pour l’installer. Nous devons réduire le nombre de scripts aléatoires en ligne et augmenter le nombre de deb pouvant être désinstallés.
La version courte:
sh
est l'interpréteur de ligne de commande (dash).
L'exécution de sh my_script
permet à dash d'interpréter le script.
./
essaie de trouver quel interpréteur utiliser, en regardant la première ligne. Par exemple. #!/bin/bash
, ou même #!/bin/ruby
(sous réserve de l'exécution de ruby my_script
).
Vous faites la différence,
avec sh
, vous exécutez un programme qui interprétera les lignes de votre script comme si vous les aviez tapées à l'invite interactive du terminal,
avec ./
, vous créez un raccourci en supposant que le script est juste ici dans le répertoire dans lequel vous vous trouvez ET il sera exécutable (parce que par exemple vous avez émis chmod +x myscript.sh
), en sauvegardant vous avez un temps précieux pour les temps futurs: -)
Il y a trois raisons principales pour lesquelles vous pourriez avoir une erreur:
chmod +x <myscriptname.sh>
pour résoudre ce problème noexec
") /usr/local/bin
#!
a une erreur #!/bin/sh
ou #!/bin/bash
Si votre première ligne semble correcte, mais ne fonctionne toujours pas, assurez-vous que le fichier n'a pas de terminaison de ligne DOS.
L’erreur ressemblerait à ceci:
$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory
Vous pouvez résoudre le problème en exécutant dos2unix <myscriptname.sh>
ou, si vous ne l’avez pas, dans perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>
.
Et la réponse est que sh est le nom du shell très populaire. Mais dépassé et remplacé par d'autres. De nos jours, sh est lié à d'autres shells installés sur la machine. par exemple. J'ai bash posé là-bas. L'exécution de n'importe quel shell à partir de sh déclenche généralement un mode de "compatibilité" avec le comportement "shell" d'origine.
La solution est donc assez simple. Regardez ce qui se trouve derrière la commande sh (ls -al / bin / sh), et mettez #! / Bin / importe_you_find_there en première ligne (ou s'il y a quelque chose comme ça dans votre script, éditez-le).
Et alternativement, il peut y avoir un bug dans le script lui-même. Comme la dépendance rencontrée par sh, mais pas l’interpréteur réellement utilisé.
mkdir ~/bin ; cp myscript.sh ~/bin/
echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ;
Pas /usr/sbin
, que pour les outils d'administration non essentiels, /usr/local/bin
est un meilleur choix si vous ne voulez pas avoir un ~/bin/
, mais en évitant sudo
autant que
possible est conseillé.
Lire d'autres questions sur les étiquettes command-line scripts executable