J’ai un script qui utilise shebang: #!/bin/sh
, mais lorsque je l’exécute sur mon terminal Ubuntu 14.04, cela ne fonctionne pas et indique que certaines lignes ont un opérateur inattendu.
Mon ami MacOSX pourrait exécuter ce script en utilisant le #!/bin/sh
shebang.
J’ai essayé de changer le shebang en #!/usr/bin/env bash
et, tout à coup, le script fonctionne! Qu’est-ce qui se passe ici en fait?
J’espère vraiment que je pourrai également exécuter le !#/bin/sh
shebang, de sorte que je n’aurai pas besoin de changer chaque script que j’ai.
Votre ami sur un autre ordinateur utilise probablement un système d’exploitation auquel /bin/sh
lié à /bin/bash
. Dans Ubuntu (en fait, Debian et la plupart des dérivés de Debian), /bin/sh
n’est pas lié à /bin/bash
, mais à /bin/dash
, qui ne prend pas en charge de nombreuses fonctionnalités spécifiques à bash
, mais est considérablement plus rapide.
Sur Arch Linux:
$ ls -l /bin/sh lrwxrwxrwx 1 root root 4 Sep 28 15:26 /bin/sh -> bash
Sur Ubuntu:
$ ls -l /bin/sh lrwxrwxrwx 1 root root 4 Feb 19 2014 /bin/sh -> dash
Si vous utilisez un shebang, dites-le. Comme votre script contient bash
-isms, utilisez /bin/bash
dans le shebang. Ou écrivez un code portable, conforme à POSIX.
Vous pouvez accélérer ce processus en utilisant le programme checkbashisms
mentionné dans cet article de LWN . Cela fait partie du paquet devscripts
, donc installez-le d’abord:
sudo apt-get install devscripts
Ainsi:
checkbashisms /path/to/script.sh || sed -i '1 s;/bin/sh;/bin/bash;' /path/to/script.sh
Vous pouvez convertir ceci en un script (par exemple, convert.sh
):
#! /bin/sh for i do checkbashisms "$i" if [ $? = "1" ] then sed -i '1 s;/bin/sh;/bin/bash;' "$i" fi done
Le code de retour spécifique de 1
signifie que checkbashisms
trouvé un bash
possible, et que les autres valeurs de retour indiquent d’autres problèmes (fichier non lisible, fichier manquant, etc.), ce qui permet de rechercher cette valeur de retour particulière.
Et puis appelez-le avec:
./convert.sh /path/to/first/script.sh /path/to/second/script.sh # or ./convert.sh *.sh # or find . -iname '*.sh' -exec ./convert.sh {} +
Remplacez /bin/sh
par un lien symbolique vers /bin/bash
.
Lecture recommandée:
bash
et dash
et indique les modifications nécessaires. /bin/sh
– similaire. Dans mon cas, le problème était l’exportation de la définition de variable IFS
dans ~ / .bashrc (~ / .profile)
#Loop over filenames with spaces export IFS=$'\n'
Lorsque changé pour soit
export IFS=$' \t\n' #default according to man dash
ou
IFS=$'\n'
Les scripts #! / bin / sh ont recommencé à fonctionner. Dans ce dernier cas, la définition ne se propage plus aux processus forked / bin / sh. La signification de IFS est expliquée ici et sa définition sur ‘\ n’ pose des problèmes dans les scripts interprétés par dash shell, qui peut être le shell par défaut /bin/sh -> dash
associé à votre dissortingbution (par exemple, debian).