/ usr / bin / env: php: Aucun fichier ou répertoire de ce type

9

Je souhaite utiliser le script .sh pour le déploiement de mon application. Ce script se trouve sur mon serveur domestique (serveur Ubuntu 15.10), marqué comme exécutable. L'accès à ce script se fait via ssh, en utilisant ce tutoriel, j'ai configuré la connexion ssh, qui exécute ce script. Donc, fondamentalement, je viens d'appeler ssh [email protected] someArgumentset il exécute mon script avec someArgumentscomme paramètres. L'utilisateur deployera uid = 0, donc c'est fondamentalement root(cela sera changé à l'avenir, je l'ai défini uniquement pour éliminer les problèmes d'autorisations jusqu'à ce qu'il fonctionne bien).

Et c'est là que les choses deviennent délicates. Le script rend compte /usr/bin/env: php: No such file or directoryà la commande /bin/composer install(à l'aide de Composer ). Les choses sont d'autant plus bizarres que je regarde ce script. Avant cette ligne, il est également appelé /bin/composer self-updateet /bin/composer -V, qui s'exécute correctement et affiche une sortie correcte.

J'ai vérifié les choses suivantes:

  • /usr/bin/env php -vaffiche la version PHP correcte (identique à /usr/bin/php -v)
  • whereis php affiche php: /usr/bin/php /usr/local/bin/php /usr/share/man/man1/php.1.gz
  • php5-cli le package est installé et la dernière version
  • $PATH contient /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
  • which env affiche /usr/bin/env

J'ai également essayé les choses suivantes:

  • exécuter le script directement bash deploy.shsous root (car il est le même que cet utilisateur) - fonctionne parfaitement sans erreurs
  • exécution directe de commandes défaillantes - également parfaitement sans erreurs

Donc cela me semble être un cas très spécifique, pourquoi cette commande ne fonctionne pas. J'ai passé 12 heures à le déboguer et je suis à court d'idées ici.

PS: une erreur similaire ( /usr/bin/env: node: No such file or directory) se produit lorsqu'il y a bower install(à l'aide de Bower ), mais pas lors de l'exécution npm install(à l'aide de NPM ).

Tomáš Blatný
la source
Courez à la sh deployplace de bash deploy(peut-être un bashisme). Comment avez-vous vérifié les " choses suivantes "? Je recommande de les vérifier dans le script, afin que vous puissiez découvrir d'éventuels remplacements et désinfections d'envs.
Giacomo Catenazzi
concernant les " choses suivantes ": je les ai ajoutées au début du script deploy.sh et elles produisent ces choses que je remets en question. La même sortie est quand je les exécute seul, cependant.
Tomáš Blatný
sh deployet les bash deploydeux donnent les mêmes résultats
Tomáš Blatný
Montrez cette ligne ici, s'il vous plaît. Je vous recommande de remplacer votre commande php sur cette ligne de votre script par une sortie dans un fichier pour examiner les variables d'environnement au moment d'appeler / usr / bin / env:/usr/bin/env > environment.txt
Oleg Bolden

Réponses:

6

Assurez-vous que les fins de ligne et / ou les espaces invisibles ne causent pas le problème.

Supprimez les espaces dans la première ligne du script et insérez-en de nouveaux, en veillant à ne pas maintenir CTRL enfoncé tout en appuyant sur espace.

Assurez-vous également que vous ne disposez pas de fins de ligne DOS (CR + LF). Voir /programming/82726/convert-dos-line-endings-to-linux-line-endings-in-vim pour plus de détails.

neuhaus
la source
J'utilise IDE, qui vérifie automatiquement (et convertit) CR + LF en LF uniquement, supprime la nomenclature et se soucie des caractères blancs, mais je l'ai revérifié et cela semble correct (ne fonctionne toujours pas). Merci quand même
Tomáš Blatný
4

Manière la plus simple .... changer le shell de l'utilisateur en script.

/ etc / passwd

Before:
deploy:x:0:0:,,,:/root:/bin/bash

After:
deploy:x:0:0:,,,:/root:/scripts/deploy.sh

Exemple de script (assurez-vous que le bit d'exécution est défini chmod + x)

/scripts/deploy.sh

#!/bin/bash 
PATH=$PATH:/moo etc...
moo.sh

Échantillon Fonctionne à chaque fois! Vous devriez même pouvoir utiliser le script pour dépanner / déboguer toutes les variables env que vous pourriez ressentir comme non définies, etc.

Remarque: Il est recommandé de toujours QUALIFIER ENTIÈREMENT les chemins d'accès pour tous les scripts, exécutables, etc.

C'était facile .. Merci d'avoir posté ..

Référence: format / etc / passwd

NotAdmin Dave
la source
Belle réponse, mais en fait, je n'utilise jamais directement l'utilisateur sur le serveur, je fais toujours un sshserveur, et par voie authorized_keys, le script est appelé, puis la connexion se termine. Comment dois-je modifier authorized_keyspour que cela fonctionne?
Tomáš Blatný
Cela devrait fonctionner de la même manière. Vous vous authentifieriez via une clé et tant que le shell est défini sur le script du compte distant en question dans le fichier / etc / passwd du serveur distant, le script s'exécutera. Je vais ajouter une capture d'écran à mon message sous peu.
NotAdmin Dave
1
@Dave ne peut pas attendre votre livre
Burgi
Merci pour votre réponse, cela n'a pas résolu mon problème, mais c'était pour moi le plus intéressant et en fait résolu les autres problèmes que j'avais. Vous a donné la prime, merci encore
Tomáš Blatný
4

La envcommande cherchera à travers un utilisateur $PATHpour trouver le premier exécutable du nom donné. Donc, /usr/bin/env phprecherchera un fichier exécutable appelé phpdans l'un des répertoires $PATHde l'utilisateur qui l'exécute.

Dans votre cas, c'est presque certainement parce que lorsque vous exécutez une commande ssh, vous ne démarrez pas un shell complet et ne lisez pas réellement les fichiers d'initialisation de votre shell. Vous pouvez le vérifier en exécutant cette commande (notez les guillemets simples):

ssh deployer@XXX.com 'echo $PATH'

Et comparer la sortie à ce que vous obtenez si vous ssh [email protected]et puis exécutez echo $PATH. Sur mon système. par exemple:

$ echo $PATH
/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:

$ ssh localhost 'echo $PATH'
/usr/bin:/bin:/usr/sbin:/sbin

Par conséquent, le $PATHfichier auquel votre script a accès lorsqu'il est exécuté ssh [email protected]n'est pas le même que lorsque vous vous connectez pour le tester.

Dans tous les cas, la solution simple consiste à utiliser le chemin complet vers l'interpréteur au lieu de env. Les deux envchemins et les chemins complets ont leurs avantages et leurs inconvénients mais, dans ce cas, le chemin est plus sûr:

#!/usr/bin/php
terdon
la source
ITYM " notez les guillemets simples" pas " pas ".
dave_thompson_085
@ dave_thompson_085 en effet je l'ai fait, merci.
terdon
J'utilise en fait des chemins complets partout, comme je l'ai mentionné dans ma question, l'erreur est signalée dans la composer install commande, que je ne peux évidemment pas modifier. Tout $PATHva bien, comme je l'ai mentionné dans ma question aussi, j'ai vérifié toutes les choses en les ajoutant dans le script et en les exécutant à distance via la connexion ssh. De plus, je ne peux pas vérifier le ssh [email protected] 'echo $PATH'comme vous l'avez déclaré, car ma connexion ssh est limitée à un seul script, mais je ne l'ai pas vérifié quand j'ajoute $ PATH à ce script (indiqué ci-dessus) Quoi qu'il en soit, merci pour votre réponse et acceptez + 1 pour m'avoir expliqué la envchose
Tomáš Blatný
@ TomášBlatný eh bien, vous utilisez env quelque part, ou vous ne verriez pas cette erreur. Je ne connais pas le compositeur mais vous devrez probablement copier ou lier l'exécutable php à un répertoire sur son chemin. Ce genre de chose est difficile à déboguer car il y a tellement de choses qui dépendent les unes des autres.
terdon
C'est vrai, envest en fait appelé à l'intérieur du compositeur. Mais cela ne résout pas le problème, pourquoi certains appels de compositeur passent, d'autres non. Cependant, j'examinerai plus avant cela en examinant son code. Merci pour votre temps
Tomáš Blatný
2

Est-il possible d'avoir bashbesoin d'une réinitialisation de sa table de hachage?

Si c'est le cas, vous pouvez essayer d'ajouter hash -rquelque part dans votre script, ce qui oblige le shell à parcourir à $PATHnouveau plutôt que de s'appuyer sur des informations (éventuellement obsolètes) de la table de hachage.

Si nécessaire, hashpeut également permettre au shell de mémoriser les chemins d'accès aux exécutables installés dans des emplacements non standard à l'aide de l' -poption, ou d'oublier les chemins d'accès avec l' -doption.

Sources:

https://unix.stackexchange.com/a/86017/121251
https://stackoverflow.com/a/22543353/2146843

flyingfinger
la source
Cela n'a pas résolu le problème pour moi, mais c'est une bonne connaissance, alors je vous ai ajouté un +1
Tomáš Blatný
1

On dirait que vous devez peut-être ajouter du php à votre chemin. Essayer:

vim ~/.bashrc
PATH=$PATH:/usr/local/bin/php
export PATH

Vous pouvez également vérifier où réside votre php pour vous assurer que le chemin y est correct. Essayer:

which php
Jeramy
la source
Eh bien, ce n'est pas le problème, car les php -vsorties de la version correcte de PHP et les composer --versionsorties de la version du compositeur. Comme je l'ai dit, le problème est dans une seule commande.
Tomáš Blatný
1

Il est clair que vous avez un problème de chemin, car votre script de déploiement ne peut pas trouver les éléments qui se trouvent définitivement sur le chemin lorsque vous effectuez une connexion ssh normale.

La première chose à faire pour confirmer que vous avez un problème avec PATH est de mettre à jour votre script de déploiement pour enregistrer la sortie de envou au moins echo $PATH. Je suppose que la façon dont votre script de déploiement est appelé, $ PATH n'est pas défini comme vous vous y attendez. Cette sortie de débogage confirmera / infirmera ma théorie.

J'ai regardé le tutoriel que vous avez suivi. Vous devriez probablement vous assurer lors de la mise à jour de l' command=être command="/bin/sh /path/to/your/script..."si vous ne l'avez pas déjà fait pour vous assurer que votre script est exécuté par le bon shell.

Si vous avez un problème avec PATH, une solution rapide / sale consiste simplement à définir explicitement PATH au début de votre script de déploiement.

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"

Explication détaillée et autres options ...

Sous Linux, lorsque les commandes sont exécutées, elles héritent de l'environnement de leur processus parent.

Lorsque vous vous connectez en tant qu'utilisateur normal via SSH, il se passe des choses (comme exécuter / etc / bashrc / etc / profile ~ / .bash_profile ~ / .bashrc etc.). À ce stade, vous avez peut-être mis à jour l'environnement de votre processus en faisant des choses comme export PATH="$PATH:~/mybin"dans ces scripts. Désormais, tous les futurs processus que vous exécuterez hériteront de votre environnement actuel.

L'exécution d'une commande au lieu d'obtenir un shell de connexion signifie que la commande est exécutée par le démon ssh et héritera de l'environnement du processus du démon ssh ... qui est probablement différent de votre environnement en tant qu'utilisateur connecté.

La page de manuel pour les clés autorisées couvre ce qui se passe après l'authentification. Concernant l'environnement:

  1. Lit le fichier ~ / .ssh / environnement, s'il existe, et les utilisateurs sont autorisés à changer leur environnement. Voir l'option PermitUserEnvironment dans sshd_config (5).

Donc , l'endroit approprié à l' environnement de configuration pour le processus est en ~/.ssh/environment~est le répertoire personnel de l'utilisateur qui est authentifié pour exécuter la commande. Vous devez également vérifier votre sshd_config pour vous assurer que PermitUserEnvironment est autorisé.

~/.ssh/environment le format est également spécifié dans la page de manuel bien sûr.

         This file is read into the environment at login (if it exists).
         It can only contain empty lines, comment lines (that start with
         '#'), and assignment lines of the form name=value.  The file
         should be writable only by the user; it need not be readable by
         directory becomes accessible.  This file should be writable only
         by the user, and need not be readable by anyone else.

Une autre façon de spécifier l'environnement sans utiliser la méthode mentionnée ci-dessus consiste à utiliser l' environment="NAME=value"option dans le fichier authorized_keys. Voir la page de manuel que j'ai liée ci-dessus pour plus de détails.

mattpr
la source
Concernant Without knowing exactly how you have setup your deploy script to run: dans ma question au début, il y a un lien, comment je l'ai mis en place (en utilisant ~/.ssh/authorized_keys. Merci pour le conseil avec la commande de mise à jour, je l'ai essayé, mais malheureusement sans aucune différence. Veuillez accepter un +1 pour cette idée
Tomáš Blatný
Avez-vous essayé de mettre à jour votre script de déploiement pour imprimer le $ PATH actuel? Pourriez-vous publier le résultat? Si cela ne correspond pas à ce que vous attendez, vous pouvez simplement essayer de définir explicitement le CHEMIN comme je l'ai suggéré au début de votre script de déploiement.
mattpr