web-dev-qa-db-fra.com

Le script shell ne peut être exécuté qu'avec la commande sh

J'ai un petit script sh que j'utilise pour sauvegarder sur un serveur distant. Cela a fonctionné sur Ubuntu 16.04 pendant des années, mais maintenant, le 18.04, il échoue. Au début, je pensais que c'était un problème avec anacron, mais maintenant je pense que c'est un problème avec le script lui-même ou avec dash. Voici ce qui se passe:

stefan@stefan-Aspire-F5-573T:/etc/cron.daily$ Sudo chmod +x rsync-doc-script 
[Sudo] Mot de passe de stefan : 
stefan@stefan-Aspire-F5-573T:/etc/cron.daily$ ./rsync-doc-script 
/bin/sh: 0: Can't open *
stefan@stefan-Aspire-F5-573T:/etc/cron.daily$ sh rsync-doc-script
opening connection using: ssh -i /home/stefan/.ssh/id_rsa -l totem MouseHouse rsync --server -vvlogDtprze.iLsfxC . /totembackup/totemdoc  (11 args)
ssh: connect to Host mousehouse port 22: Connection refused
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.2]
stefan@stefan-Aspire-F5-573T:/etc/cron.daily$ 

L'erreur can't open * empêche le script de s'exécuter correctement lorsqu'il est exécuté par run-parts. Pourquoi cette erreur se produit-elle?

Il n'est pas pertinent que dans la dernière ligne, lors de l'exécution du script, il ne puisse pas établir de connexion. Le serveur est maintenant éteint.

Voici le script:

#!/bin/sh                                                                                     *
rsync -azvv -e "ssh -i /home/stefan/.ssh/id_rsa" /home/stefan/Documents/ totem@MouseHouse:/totembackup/totemdoc

5
Stefan Dawydiak

Je ne peux pas dire avec certitude, mais il semble que vous ayez une faute de frappe sur la première ligne où il y a un _ * vers la droite.

#!/bin/sh                                                                                     *

^^^ Faites défiler vers la droite pour le voir.

Exemple

$ cat script.bash
#!/bin/sh                    *
echo hi

Exécutez directement:

$ ./script.bash
/bin/sh: *: No such file or directory

Exécutez via sh:

$ sh script.bash
hi

Conseils généraux

Il est généralement conseillé d'utiliser la coque exacte que vous attendez avec votre Shebang. Si vous pensez que vous rencontrez des problèmes où vous pensez que dash ou un autre Shell est utilisé, vous pouvez toujours rendre votre Shebang explicite en le changeant de #!/bin/sh comme votre Shebang #!/bin/bash.

Ce qui précède est basé sur votre commentaire ci-dessous:

mais maintenant je pense que c'est un problème avec le script lui-même ou avec le tiret.

9
slm

L'erreur can't open * empêche le script de s'exécuter correctement lorsqu'il est exécuté par run-parts. Pourquoi cette erreur se produit-elle?

Lorsque vous exécutez un fichier1 ce n'est pas un exécutable binaire, mais c'est un fichier texte avec un Shebang (la première ligne du fichier commence par #!), le noyau (sans l'aide d'aucun shell) construit une commande qui est la ligne Shebang (la partie après le #!) suivi de la ligne de commande d'origine au niveau de l'utilisateur. Par exemple, si doc-script commence

#!/bin/sh -x

et il est invoqué

./doc-script bashful dopey

puis le noyau construit et exécute la commande suivante:

/bin/sh -x ./doc-script bashful dopey

ce qui oblige le shell à lire et interpréter le doc-script script, avec xtrace (-x) ensemble d'options, et avec $1 = bashful et $2 = dopey. (Naturellement, $0 est ./doc-script.) Si la commande d'origine fournie par l'utilisateur est

./doc-script b* ??p* [ghs]*

le shell qui gère cette commande (pour simplifier, supposons qu'il s'agit du shell interactif s'exécutant sur le terminal de l'utilisateur) pourrait l'étendre à

./doc-script bashful dopey grumpy happy sleepy sneezy

et ainsi le noyau construit et exécute la commande suivante:

/bin/sh -x ./doc-script bashful dopey grumpy happy sleepy sneezy

Mais rappelez-vous: le traitement de la ligne Shebang est fait par le noyau, pas par le Shell . Par conséquent, si le Shebang est

#!/bin/sh *

alors la commande finale et construite est

/bin/sh * ./doc-script bashful dopey grumpy happy sleepy sneezy

car l'expansion globale ne se produit pas ici. En ce qui concerne le Shell, cela ressemble à l'utilisateur tapé

/bin/sh '*' ./doc-script bashful dopey grumpy happy sleepy sneezy

et parce que * ne commence pas par -, le shell l'interprète comme un nom de fichier, il essaie donc d'exécuter un script appelé * avec $0 = *, $1 = ./doc-script, $2 = bashful, $3 = dopey, etc. Et, puisqu'il n'y a pas de script appelé *, cela échoue.
__________
1Je suppose que le processus dispose des autorisations nécessaires pour exécuter le fichier.