J'ai écrit un script simple. Quand j'ai lancé sh <myscriptname.sh>
, j'ai obtenu le bon résultat, mais quand j'ai lancé ./<myscriptname.sh>
, j'ai eu une erreur.
Quelle est la différence entre quand je fais sh
et ./
?
Lorsque vous exécutez un script en transmettant le nom de fichier au programme d'interprétation 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 "filename.sh". L'interprète sh
est en train d'ouvrir le fichier.
Par ailleurs, si vous exécutez le script lui-même, le système appelle le programme interprète 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 bang:
#!/bin/bash
# bash script here
Une ligne éclatée est le toute première ligne dans le script et commence par les deux mêmes caractères #!
. Il s’agit de ce que le système lit quand il essaie d’exécuter le script, puis il le transmet au programme immédiatement après. Notez que cette ligne n'a rien à voir avec bash et fonctionne aussi bien pour python et Perl, même si ce sont des langages très différents. Vous utiliseriez par exemple #!/usr/bin/python
et le suivriez avec le code python.
Une fois que vous avez votre script, assurez-vous d’avoir défini les autorisations d’exécution:
chmod a+x filename.sh
Ensuite, vous pouvez exécuter le script en tant que processus propre:
./filename.sh
Ou placez le fichier dans un emplacement connu avec un nom de programme Nice, comme /usr/sbin
, et exécutez-le n'importe où:
Sudo cp filename.sh /usr/sbin/program-name
program-name
Et c’est vraiment l’avantage pratique d’utiliser la ligne bang avec les autorisations adéquates - il s’agit du déploiement . Il est très difficile d'amener les utilisateurs à exécuter un script s'ils doivent se rappeler avec quel programme exécuter le script. N'oubliez pas de donner un chemin complet au script chaque fois qu'ils veulent l'exécuter. Par exemple, le mettre dans /usr/local/bin
et le rendre exécutable peut épargner énormément de chagrin à ceux qui essaient d’utiliser votre script. Ces programmes deviennent alors disponibles pour tous les utilisateurs de votre ordinateur.
C'est aussi bon pour l'identification. Si vous allez dans le programme top
name__, un script exécuté sans la ligne bang n'aura que le nom de l'interpréteur, à savoir bash
name__, Perl
ou python
name__. Mais si un script est exécuté avec les autorisations appropriées, le nom du script s'affiche.
Remarque: Si vous souhaitez distribuer un script accessible à tous, créez une page de manuel et un paquet deb pour l'installer. Nous devons réduire le nombre de scripts aléatoires en ligne et augmenter le nombre de debs pouvant être désinstallés.
La version courte:
sh
est l'interpréteur de ligne de commande (tiret).
Lancer sh my_script
fait en sorte que dash interprète le script.
./
essaie de trouver quel interpréteur utiliser en regardant la première ligne. Par exemple. #!/bin/bash
, ou même #!/bin/Ruby
(comme indiqué par l'exécution de Ruby my_script
).
La différence que vous faites est,
avec sh
, vous exécutez un programme qui interprétera les lignes de votre script exactement comme si vous les aviez tapées sur l'invite interactive du terminal,
avec ./
vous créez un raccourci en partant du principe que le script se trouve exactement dans le répertoire actuel dans lequel vous êtes assis ET qu'il sera exécutable (parce que vous avez par exemple émis chmod +x myscript.sh
), vous permettant ainsi de gagner un temps précieux :-)
Vous pouvez obtenir une erreur pour trois raisons principales:
chmod +x <myscriptname.sh>
pour résoudre ce problèmenoexec
")/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 ne comporte pas de fin de ligne DOS.
L'erreur ressemblerait à quelque chose comme ça:
$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory
Vous pouvez le réparer en exécutant dos2unix <myscriptname.sh>
, ou si vous ne l'avez pas,Perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>
.
Et la réponse est que sh est le nom de Shell très populaire. Mais obsolète et remplacé par d'autres. De nos jours, sh est lié à d’autres coques installées sur la machine. par exemple. Je l'ai mis là. L'exécution d'un shell à partir de sh déclenche généralement un mode de compatibilité avec le comportement d'origine du shell.
Donc, la solution est assez simple. Regardez ce qui se cache derrière la commande sh (ls -al/bin/sh), et mettez #!/Bin/any_you_find_there en première ligne (ou s'il y a quelque chose comme ça dans votre script, modifiez-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ète réellement utilisé.
mkdir ~/bin ; cp myscript.sh ~/bin/
echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ;
/usr/sbin
n'est pas, c'est pour les outils administratifs non essentiels, /usr/local/bin
est un meilleur choix si vous ne voulez pas avoir un ~/bin/
, mais il est préférable d'éviter Sudo
autant que possible.