.sh spécifiant l'extension?

12

Pourquoi certains systèmes exécuteront-ils un .shfichier simplement en spécifiant le nom du fichier sans extension et d'autres nécessitent un nom plus une extension? Dans mon cas, j'essaie d'écrire une série de commandes en suivant ces instructions .

Je spécifie l'extension maintenant mais pouvoir exécuter les commandes sans .shserait préférable.

Philip Kirkbride
la source
4
L'utilisation .shen tant qu'extension est dans de nombreuses circonstances considérée comme une mauvaise pratique: elle est contraire à la façon dont les autres commandes sont nommées (vous ne les exécutez pas ls.elf), elle est souvent trompeuse (si vous foo.shcommencez par #!/bin/bash, alors l'exécution sh foo.shs'exécutera avec un interpréteur différent de celui pour lequel elle est conçue) ), et si vous réécrivez foo.shpour être un programme Python, l'utilisation de cette extension signifie que vous devez choisir entre conserver le nom désormais trompeur et réécrire chaque programme qui l'appelle.
Charles Duffy
2
... où il est une meilleure pratique est des bibliothèques shell, pas de commandes avec +xjeu - où foo.shest une bibliothèque qui peut être affiché dans une POSIX, foo.bashpeut être affiché dans bash, foo.kshen ksh, etc.
Charles Duffy

Réponses:

39

Tu es confus. L' .shextension n'est qu'un indice pour les humains et n'a absolument aucun effet sur la façon dont le système gère le fichier. Unix / Linux n'a pas fait l' Secrets.pdf.exeerreur de Windows .

Voici ce qui se passe lorsque vous tapez foo:

  1. Redirection pour STDIN, STDOUTet STDERRsont mis en place.

  2. Le shell vérifie sa table de hachage interne pour voir s'il connaît déjà une $PATHentrée pour foo. S'il n'en existe pas, le shell recherche dans les répertoires $PATH, à la recherche d'un fichier appelé foodont le bit d'exécution est défini dans ses autorisations de fichier. Première foovictoire.

  3. Si les deux premiers octets du fichier le foosont #!, la chaîne suivante est le nom d'un interpréteur à exécuter. #!/bin/bashIntroduit ainsi un script Bash, #!/usr/bin/perlintroduit un script Perl, etc.

  4. Si le fichier commence par \177ELF, c'est un exécutable binaire et le ld.sodémarre.

Lisez man execveet man ld.sopour une explication plus détaillée.

waltinator
la source
15
Oui, sous Linux, vous pouvez double-cliquer sur Secrets.pdf sans aucun indice du nom qu'il s'agit en fait d'un exécutable;)
OrangeDog
1
@OrangeDog Je sais que vous plaisantez, mais j'ai l'impression que je dois souligner que le bit exécutable ( chmod +x) résout à peu près cela, non?
wchargin
3
@WChargin Cela dépend du comportement de votre système de fichiers (par exemple, un partage réseau monté ou une partition NTFS peut définir le xbit de manière optimiste sur tout) et d'où le fichier provient (tout processus contrôlant le répertoire peut être amené à définir les autorisations) . Donc, cela l' atténue , mais je ne dirais pas qu'il le résout .
IMSoP
2
@WChargin, pour l'instant, mais je pense que son point de vue est que les gestionnaires de fichiers ne montrent généralement pas le bit exécutable, c'est-à-dire qu'il n'y a pas de "conseil aux humains" comme une extension.
Paul Draper
1
Je ne clique jamais par erreur Secrets.pdf.exeparce que je désactive toujours la hide file extensionfonction stupide
phuclv
12

Le point clé est le suivant: les extensions ne sont pas pertinentes dans tout système système de type Unix. Un nom de fichier est juste un nom et n'a aucun effet sur l'exécution ou non d'un script ou d'un exécutable compilé . Un programmeur peut ajouter une .shextension pour désigner qu'un fichier est un script shell, ou .pypour un script python, mais contrairement à Windows, tout unix ne se soucie pas du nom, il se soucie des autorisations.

Ce qui importe, c'est l'autorisation exécutable accordée à un fichier. Avec lequel vous pouvez vérifier

ls -l /path/to/file

Exécuter des exécutables

Pour exécuter un script, il existe généralement plusieurs méthodes.

  • Si votre répertoire actuel est le même que le script et que le script dispose d'autorisations exécutables, vous pouvez l'exécuter comme tel ./my_script_name. Le .répertoire courant moyen.
  • Si votre répertoire actuel est différent et que le script dispose d'autorisations exécutables, vous pouvez l'exécuter en spécifiant le chemin complet: /home/user/bin/my_script_name

(Les deux méthodes ci-dessus reposent sur un ensemble d'autorisations exécutables; que le fichier fasse partie de la $PATHvariable ou non. La présence de la #!ligne est également importante; sans elle, le script sera exécuté par le shell actuel que vous avez ouvert. Si j'ai un cshscript sans cette ligne, et essayez de l'exécuter en bash avec ./my_script.csh, cela échouera)

  • Si votre script se trouve dans un répertoire faisant partie de votre $PATHvariable, vous pouvez l'exécuter simplement en appelant le nom. Vous pouvez appeler la chmodcommande en ligne de commande en tapant simplement son nom car il se trouve dans le /bindossier. /binfait toujours partie de la $PATHvariable. Dans ce cas, les autorisations exécutables et l'emplacement du sujet du script
  • Spécification d'un interpréteur comme commande et d'un script comme argument. De cette façon, le script servira de fichier d'entrée à l'interpréteur.
  • Sourcing d'un fichier. Le . filename.shou source filename.shfera en sorte que le script soit traité comme s'il s'agissait d'une entrée au clavier, c'est-à-dire comme s'il était tapé directement en ligne de commande. Dans ce cas, les autorisations exécutables et l'emplacement n'ont pas d'importance

Exemples

Exemple # 1, en cours d'exécution avec interprète, pour exécuter des autorisations

$-> ls -l abc.py                                                               
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py                                                              
a
b
c

Exemple # 2, exécuté avec ./un ensemble d'autorisations exécutables, un ensemble de lignes shebang.

$-> cat abc.py                                                                 
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
   print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py                                                                   
a
b
c

Exemple # 3, s'exécutant sans jeu de lignes shebang (échoue, car bash ne peut pas lire les scripts python; aucune ligne shebang n'assume le shell actuel comme interpréteur)

$-> cat abc.py                                                                 
for letter in 'a' 'b' 'c' :
   print letter
$-> ./abc.py                                                                   
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")

Exemple # 4, exécution d'un script doté d'autorisations exécutables, dossier de formulaire défini faisant partie de la $PATHvariable

#  /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh

$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.                    
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py          
$-> # after adding the line with vi text editor, we can run
$-> abc.py                                                                     
a
b
c

L'exemple n ° 5, suppression d'une extension, s'exécute toujours car les extensions n'ont pas d'importance, mais il dispose d'autorisations et fait partie de $PATH:

$-> mv ~/bin/abc.py  ~/bin/abc                                                 
$-> abc
a
b
c
Sergiy Kolodyazhnyy
la source
J'ai exécuté la commande et j'obtiens ce '-rwxr-x ---'. Que veux-je lire et comment puis-je la modifier?
Philip Kirkbride
Ou dites-vous que je devrais simplement renommer "filename.sh" en "filename"?
Philip Kirkbride
1
@PhilipKirkbride Le nom n'est pas pertinent. Comment exécutez-vous votre commande? Où est-ce ? Le répertoire fait-il partie du vôtre PATH?
Sergiy Kolodyazhnyy
@PhilipKirkbride Permettez-moi de développer ma réponse dans une minute pour la rendre plus claire.
Sergiy Kolodyazhnyy
1
Jetez un oeil man chmodpour voir comment définir les autorisations
Nick Mertin
6

De bonnes explications ici déjà. Je voulais juste ajouter que, idéalement, vous ne devriez pas utiliser d'extensions de fichiers pour les exécutables.

Habituellement, vous devez accomplir quelque chose de relativement facile et vous commencez avec un petit script shell. Au fil du temps, vous commencez à ajouter de plus en plus de fonctionnalités à votre script, jusqu'à ce qu'il arrive un certain temps qu'il devienne impossible à maintenir ou que vous ayez besoin de fonctionnalités que vous ne pouvez pas accomplir facilement avec un script shell et pensez à réécrire ce script shell dans une autre langue (python , perl, ...?).

La réécriture à partir de zéro est généralement considérée comme une erreur, mais pour les scripts, cela peut être logique car généralement ils ne sont pas si grands ou ont beaucoup de fonctionnalités. Mais supposons qu'il est possible de réécrire à partir de zéro dans un autre langage, en conservant la fonctionnalité et les paramètres / drapeaux du script shell initial.

Les utilisateurs de ce script n'ont pas besoin d'être au courant de ce changement de langue, ils continueront à exécuter la même commande et elle continuera de fonctionner.

Si votre script a été nommé do-something.sh, il peut continuer à l'être do-something.sh, mais maintenant il est écrit en python (par exemple), et donc votre indice initial est maintenant totalement trompeur.

Carlos Campderrós
la source
4

Pour exécuter des fichiers sans extension, vous n'avez normalement pas besoin de faire grand-chose, assurez-vous simplement que vous avez (dans le cas des scripts bash) la ligne de shebang appropriée à la toute première ligne:

#!/bin/bash

alors vous devez également rendre le fichier exécutable pour le système par

chmod 755 yourfilename

C'est la même chose que l'utilisation chmod +x yourfilenamedes chiffres est facile à expliquer.

Il s'agit d'un nombre triple d'octales ajoutées, le premier nombre correspond à l'utilisateur, le second au groupe et le troisième aux autres, plus d'informations que vous pouvez trouver ici .

Et si vous êtes dans le même répertoire que votre script, n'oubliez pas d'utiliser ./comme ceci:

./yourfilename
Videonauth
la source
J'ai essayé ça. Malheureusement, aucune différence par rapport aux résultats originaux.
Philip Kirkbride
@PhilipKirkbride jetez un oeil à ma réponse révisée, cela apportera probablement un peu plus de lumière.
Videonauth
0

Le suffixe .sh peut en fait gêner, car pour l'exécuter, vous devez taper myscript.sh au lieu de simplement myscript qui ne fonctionnera pas. Mieux vaut simplement l'appeler "myscript" sans le suffixe .sh, et une utilisation rapide de la commande "file" vous dira s'il s'agit d'un exécutable binaire (format ELF sur linux) ou d'un script shell, ou de tout autre type de script.

QDOS (système d'exploitation rapide et sale, renommé plus tard en "DOS" par IBM après que Mirosoft l'ait piraté et vendu illégalement à eux) et d'autres arnaques bon marché de CP / M, y compris Windows, mélangent tout cela parce que sur ces systèmes, il n'y a pas telle que l'exécution des autorisations sur les fichiers. Cela s'est traduit par d'innombrables problèmes de sécurité au cours des 30 à 40 dernières années. En fait, il y a quelques minutes, je viens de recevoir plusieurs courriers indésirables avec un fichier zip piégé renard renommé MYPICTURE.JPG.zip :)

delt
la source