/ usr / bin / env: php: Brak takiego pliku lub katalogu

9

Chcę użyć skryptu .sh do wdrożenia mojej aplikacji. Ten skrypt znajduje się na moim serwerze domowym (Ubuntu 15.10 Server), oznaczony jako wykonywalny. Dostęp do tego skryptu odbywa się za pośrednictwem ssh, korzystając z tego samouczka, skonfigurowałem logowanie ssh, które uruchamia ten skrypt. Zasadniczo po prostu wywołuję ssh [email protected] someArgumentsi uruchamia mój skrypt someArgumentsjako parametry. Użytkownik deployerma identyfikator UID = 0, więc w zasadzie jest rootto (zostanie to zmienione w przyszłości, ustawiłem go tylko w celu wyeliminowania problemów z uprawnieniami, dopóki nie będzie działać poprawnie).

I tutaj sprawy stają się trudne. Skrypt raportuje /usr/bin/env: php: No such file or directoryprzy komendzie /bin/composer install(przy użyciu Composer ). Sprawy są dziwniejsze, im bardziej patrzę na ten skrypt. Przed tym wierszem jest także wywoływane /bin/composer self-updatei /bin/composer -V, które działa poprawnie i wyświetla prawidłowe dane wyjściowe.

Sprawdziłem następujące rzeczy:

  • /usr/bin/env php -vwyświetla poprawną wersję PHP (taką samą jak /usr/bin/php -v)
  • whereis php wyświetla php: /usr/bin/php /usr/local/bin/php /usr/share/man/man1/php.1.gz
  • php5-cli pakiet jest zainstalowany i najnowsza wersja
  • $PATH zawiera /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
  • which env wyświetla /usr/bin/env

Próbowałem także następujących rzeczy:

  • uruchomienie skryptu bezpośrednio jako bash deploy.shroot (ponieważ jest taki sam jak ten użytkownik) - działa idealnie bez błędów
  • bezpośrednie uruchamianie błędnych poleceń - również idealnie bez błędów

Wydaje mi się więc, że to bardzo szczególny przypadek, dlaczego to polecenie nie działa. Spędziłem 12 godzin na debugowaniu i nie mam tutaj pomysłów.

PS: Podobny błąd ( /usr/bin/env: node: No such file or directory) występuje, gdy jest bower install(za pomocą Bower ), ale nie występuje podczas działania npm install(za pomocą NPM ).

Tomáš Blatný
źródło
Uruchom sh deployzamiast bash deploy(może jakiś bashism). Jak sprawdziłeś „ następujące rzeczy ”? Polecam sprawdzić je w skrypcie, abyś mógł odkryć ewentualne zastąpienia i sanityzacje środowisk.
Giacomo Catenazzi
w odniesieniu do „ następujących rzeczy ”: dodałem je na początku skryptu deploy.sh i wyświetlają te rzeczy, które postawiłem pod znakiem zapytania. Jednak ten sam wynik pojawia się, gdy uruchamiam je same.
Tomáš Blatný
sh deployi bash deployoba dają takie same wyniki
Tomáš Blatný
Pokaż tę linię tutaj. Polecam zastąpienie polecenia php w tym wierszu skryptu danymi wyjściowymi do pliku w celu sprawdzenia zmiennych środowiskowych w momencie wywołania / usr / bin / env:/usr/bin/env > environment.txt
Oleg Bolden

Odpowiedzi:

6

Upewnij się, że zakończenia linii i / lub niewidoczne spacje nie powodują problemu.

Usuń spacje w pierwszym wierszu skryptu i wstaw nowe, uważając, aby nie przytrzymać CTRL podczas naciskania spacji.

Upewnij się także, że nie masz zakończeń linii DOS (CR + LF). Szczegółowe informacje można znaleźć na stronie /programming/82726/convert-dos-line-endings-to-linux-line-endings-in-vim .

neuhaus
źródło
Używam IDE, które automatycznie sprawdza (i konwertuje) tylko CR + LF na LF, usuwa BOM i dba o białe znaki, ale sprawdziłem je dwukrotnie i wydaje się być w porządku (choć nadal nie działa). W każdym razie dzięki
Tomáš Blatný
4

Najłatwiejszy sposób .... zmień powłokę użytkownika jako skrypt.

/ etc / passwd

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

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

Przykładowy skrypt (upewnij się, że bit wykonania jest ustawiony chmod + x)

/scripts/deploy.sh

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

Próba Działa za każdym razem! Powinieneś być nawet w stanie użyć skryptu do rozwiązywania problemów / debugowania zmiennych env, które możesz uważać za nie ustawione itd. ... również argumenty obsługi przekazywane do ssh również będą działać.

Uwaga: jego najlepszą praktyką jest zawsze PEŁNA KWALIFIKACJA ścieżek do wszelkich skryptów, plików wykonywalnych itp. Powyżej jest tylko przykład, który pozwala ustawić domyślną ścieżkę do wywoływania moo.sh w folderze moo;)

To było łatwe .. Dzięki za wysłanie ..

Odniesienie: format / etc / passwd

NotAdmin Dave
źródło
Dobra odpowiedź, ale tak naprawdę nigdy nie używam użytkownika bezpośrednio na serwerze, zawsze sshdo serwera, a po authorized_keyslinii, skrypt jest wywoływany, a następnie połączenie się kończy. Jak zmodyfikować, authorized_keysaby nadal działało?
Tomáš Blatný
Powinno działać tak samo. Będziesz uwierzytelniał się za pomocą klucza i dopóki skrypt ustawiony jest w skrypcie dla danego konta zdalnego w pliku / etc / passwd zdalnego serwera, skrypt będzie działał. Wkrótce dodam zrzut ekranu do mojego postu.
NotAdmin Dave
1
@Dave nie może się doczekać książki
Burgi
Dzięki za odpowiedź, nie rozwiązało to mojego problemu, ale było dla mnie najbardziej interesujące i faktycznie rozwiązało inne problemy, jakie miałem. Dałem ci nagrodę, jeszcze raz dziękuję
Tomáš Blatný
4

envKomenda będzie wyglądać przez autora $PATHdo znalezienia pierwszego wykonywalnego o podanej nazwie. Poszuka więc /usr/bin/env phppliku wykonywalnego wywołanego phpw jednym z katalogów $PATHużytkownika, który go uruchomił.

W twoim przypadku jest to prawie na pewno dlatego, że po uruchomieniu polecenia sshnie uruchamiasz pełnej powłoki i nie odczytujesz plików inicjujących powłoki. Możesz to sprawdzić, uruchamiając to polecenie (zwróć uwagę na pojedyncze cudzysłowy):

ssh deployer@XXX.com 'echo $PATH'

I porównując dane wyjściowe, co dostajesz, jeśli ssh [email protected]a następnie uruchomić echo $PATH. W moim systemie. na przykład:

$ 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

Dlatego $PATHdostęp do skryptu podczas uruchamiania ssh [email protected]nie jest taki sam, jak podczas logowania w celu przetestowania.

W każdym razie prostym rozwiązaniem jest użycie pełnej ścieżki do tłumacza zamiast env. Obie envi pełne ścieżki mają swoje zalety i wady, ale w tym przypadku ścieżka jest bezpieczniejsza:

#!/usr/bin/php
terdon
źródło
ITYM „ zwróć uwagę na pojedyncze cudzysłowy” nie „ nie ”.
dave_thompson_085
@ dave_thompson_085 rzeczywiście zrobiłem, dzięki.
terdon
Właściwie używam wszędzie pełnych ścieżek, jak wspomniałem w swoim pytaniu, błąd jest zgłaszany w composer install poleceniu, którego oczywiście nie mogę zmodyfikować. Również $PATHjest ok, jak wspomniałem również w moim pytaniu, sprawdziłem wszystkie rzeczy, dodając je do skryptu i uruchamiając zdalnie poprzez logowanie ssh. Ponadto nie mogę sprawdzić, ssh [email protected] 'echo $PATH'jak powiedziałeś, ponieważ mój login ssh jest ograniczony tylko do jednego skryptu, ale sprawdziłem go, gdy dodam $ PATH do tego skryptu (wyżej) W każdym razie dziękuję za odpowiedź i akceptuję + 1 za wyjaśnienie mi tej envrzeczy
Tomáš Blatný
@ TomášBlatný dobrze, gdzieś używasz env, inaczej nie zobaczysz tego błędu. Nie znam kompozytora, ale prawdopodobnie będziesz musiał skopiować lub połączyć plik wykonywalny php z katalogiem na ścieżce. Tego rodzaju rzeczy trudno jest debugować, ponieważ istnieje tak wiele rzeczy zależnych od siebie.
terdon
To prawda, envnazywa się tak naprawdę kompozytorem. Ale to nie rozwiązuje problemu, dlaczego niektóre połączenia kompozytora mijały, a niektóre nie. Jednak później zbadam to, sprawdzając jego kod. Dzięki za
poświęcony
2

Czy to możliwe, że bashtrzeba zresetować tabelę skrótów?

Jeśli tak, możesz spróbować dodać hash -rgdzieś w skrypcie, co zmusza powłokę do $PATHponownego przejrzenia, zamiast polegać na (prawdopodobnie nieaktualnych) informacjach z tabeli skrótów.

W razie potrzeby hashmożna również włączyć powłokę do zapamiętywania ścieżek do plików wykonywalnych zainstalowanych w niestandardowych lokalizacjach za pomocą -popcji lub zapomnienia ścieżek za pomocą tej -dopcji.

Źródła:

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

latający palec
źródło
Nie rozwiązało to dla mnie problemu, ale jest to dobra wiedza, więc dodałem +1
Tomáš Blatný
1

Wygląda na to, że musisz dodać php do swojej ścieżki. Próbować:

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

Możesz także sprawdzić, gdzie mieszka twój php, aby upewnić się, że ścieżka tam jest poprawna. Próbować:

which php
Jeramy
źródło
Cóż, to nie jest problem, ponieważ dane php -vwyjściowe mają poprawną wersję PHP i dane composer --versionwyjściowe kompozytora. Jak powiedziałem, problem występuje tylko w jednym poleceniu.
Tomáš Blatný
1

Oczywiste jest, że masz problem ze ścieżką, ponieważ skrypt wdrażania nie może znaleźć rzeczy, które zdecydowanie znajdują się na ścieżce podczas normalnego logowania ssh.

Pierwszą rzeczą, którą należy zrobić, aby potwierdzić problem ze ŚCIEŻKĄ, jest zaktualizowanie skryptu wdrażania w celu zarejestrowania danych wyjściowych envlub przynajmniej echo $PATH. Domyślam się, że sposób, w jaki wywoływany jest skrypt wdrażania, $ PATH nie jest ustawiony zgodnie z oczekiwaniami. To wyjście debugowania potwierdzi / zaprzeczy mojej teorii.

Spojrzałem na samouczek, którego użyłeś. Powinieneś upewnić się aktualizacji command=się command="/bin/sh /path/to/your/script..."jeśli nie masz jeszcze upewnić się, że skrypt jest uruchamiany przez prawe powłoki.

Jeśli masz problem ze ŚCIEŻKĄ, szybką / brudną poprawką jest po prostu jawne ustawienie ŚCIEŻKI na początku skryptu wdrażania.

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

Szczegółowe wyjaśnienie i dalsze opcje ...

W systemie Linux podczas uruchamiania poleceń dziedziczą środowisko procesu nadrzędnego.

Kiedy logujesz się jako zwykły użytkownik przez SSH, zdarzają się rzeczy (na przykład uruchamianie / etc / bashrc / etc / profile ~ / .bash_profile ~ / .bashrc itp.). W tym momencie mogłeś zaktualizować środowisko swojego procesu, wykonując czynności takie jak export PATH="$PATH:~/mybin"w tych skryptach. Teraz wszelkie przyszłe procesy, które uruchomisz, odziedziczą twoje obecne środowisko.

Uruchomienie polecenia zamiast uzyskania powłoki logowania oznacza, że ​​polecenie jest uruchamiane przez demona ssh i odziedziczy środowisko procesu demona ssh ... co prawdopodobnie różni się od środowiska jako zalogowany użytkownik.

Strona podręcznika dla autoryzowanych kluczy obejmuje to, co dzieje się po uwierzytelnieniu. W odniesieniu do środowiska:

  1. Odczytuje plik ~ / .ssh / environment, jeśli istnieje, a użytkownicy mogą zmieniać swoje środowisko. Zobacz opcję PermitUserEnvironment w sshd_config (5).

Tak więc odpowiednim miejscem do skonfigurowania środowiska dla procesu jest miejsce, w ~/.ssh/environmentktórym ~znajduje się katalog domowy użytkownika uwierzytelnionego do uruchomienia polecenia. Musisz także sprawdzić sshd_config, aby upewnić się, że PermitUserEnvironment jest dozwolone.

~/.ssh/environment Format jest również określony na stronie podręcznika.

         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.

Alternatywnym sposobem określenia środowiska bez korzystania z wyżej wymienionej metody jest użycie environment="NAME=value"opcji w pliku uprawnione_klucze. Szczegółowe informacje można znaleźć na stronie podręcznika, do której odsyłam powyżej.

matpr
źródło
Odnośnie Without knowing exactly how you have setup your deploy script to run: w moim pytaniu na początku jest link, jak go skonfigurować (używając ~/.ssh/authorized_keys. Dzięki za wskazówkę z poleceniem aktualizacji, wypróbowałem to, ale niestety bez różnicy. Jednak później zbadam to i spróbuję różnych powłok Przyjmij +1 za ten pomysł
Tomáš Blatný
Czy próbowałeś zaktualizować skrypt wdrażania, aby wydrukować bieżącą ścieżkę $ PATH? Czy możesz opublikować wynik? Jeśli nie zgadza się z oczekiwaniami, możesz po prostu jawnie ustawić PATH, tak jak zasugerowałem na początku skryptu wdrażania.
mattpr