/ usr / bin / env: php: Tidak ada file atau direktori tersebut

9

Saya ingin menggunakan skrip .sh untuk penerapan aplikasi saya. Skrip itu ada di server rumah saya (Server Ubuntu 15.10), ditandai sebagai dapat dieksekusi. Akses ke skrip ini dilakukan melalui ssh, menggunakan tutorial ini , saya telah mengatur ssh login, yang menjalankan skrip itu. Jadi pada dasarnya saya hanya memanggil ssh [email protected] someArgumentsdan menjalankan skrip saya dengan someArgumentssebagai parameter. Pengguna deployermemiliki uid = 0, jadi pada dasarnya root(ini akan diubah di masa depan, saya telah menetapkannya hanya untuk menghilangkan masalah izin sampai berfungsi dengan baik).

Dan di sinilah semuanya menjadi rumit. Skrip melaporkan /usr/bin/env: php: No such file or directorypada perintah /bin/composer install(menggunakan Komposer ). Hal-hal semakin aneh, semakin saya melihat skrip itu. Sebelum baris ini, ada juga yang dipanggil /bin/composer self-updatedan /bin/composer -V, yang keduanya berjalan dengan benar dan menampilkan output yang benar.

Saya telah memeriksa hal-hal berikut:

  • /usr/bin/env php -vmenampilkan versi PHP yang benar (sama seperti /usr/bin/php -v)
  • whereis php menampilkan php: /usr/bin/php /usr/local/bin/php /usr/share/man/man1/php.1.gz
  • php5-cli paket diinstal dan versi terbaru
  • $PATH mengandung /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
  • which env menampilkan /usr/bin/env

Saya juga sudah mencoba beberapa hal berikut:

  • menjalankan skrip secara langsung seperti di bash deploy.shbawah root (karena itu sama dengan pengguna itu) - berfungsi sempurna tanpa kesalahan
  • menjalankan perintah yang gagal secara langsung - juga sempurna tanpa kesalahan

Jadi ini bagi saya adalah kasus yang sangat spesifik, mengapa perintah ini tidak berfungsi. Saya menghabiskan 12 jam men-debug itu dan saya kehabisan ide di sini.

PS: Kesalahan yang serupa ( /usr/bin/env: node: No such file or directory) terjadi ketika ada bower install(menggunakan Bower ), tetapi tidak ketika menjalankan npm install(menggunakan NPM ).

Tomáš Blatný
sumber
Jalankan sh deploybukannya bash deploy(mungkin beberapa bashism). Bagaimana Anda memeriksa " hal-hal berikut "? Saya sarankan untuk memeriksanya dalam skrip, sehingga Anda dapat menemukan akhirnya penggantian dan sanitasi envs.
Giacomo Catenazzi
mengenai " mengikuti hal-hal ": Saya menambahkan mereka untuk memulai skrip deploy.sh dan mereka menampilkan hal-hal ini yang saya tanyakan. Output yang sama adalah ketika saya menjalankannya sendiri.
Tomáš Blatný
sh deploydan bash deploykeduanya memberikan hasil yang sama
Tomáš Blatný
Tolong tunjukkan baris itu di sini. Saya merekomendasikan Anda untuk mengganti perintah php Anda di baris ini dalam skrip Anda dengan output ke file untuk memeriksa variabel lingkungan pada saat memanggil / usr / bin / env:/usr/bin/env > environment.txt
Oleg Bolden

Jawaban:

6

Pastikan bahwa ujung garis dan / atau ruang yang tidak terlihat tidak menyebabkan masalah.

Hapus spasi di baris pertama skrip dan masukkan yang baru, pastikan untuk tidak menahan CTRL sambil menekan spasi.

Juga, pastikan Anda tidak memiliki ujung garis DOS (CR + LF). Lihat /programming/82726/convert-dos-line-endings-to-linux-line-endings-in-vim untuk detailnya.

neuhaus
sumber
Saya menggunakan IDE, yang secara otomatis memeriksa (dan mengonversi) CR + LF ke LF saja, menghapus BOM dan peduli dengan karakter putih, tapi saya mengeceknya, dan tampaknya ok (masih belum berfungsi). Terima kasih
Tomáš Blatný
4

Cara termudah .... ubah shell pengguna sebagai skrip.

/ etc / passwd

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

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

Contoh skrip (pastikan bit eksekusi diatur chmod + x)

/scripts/deploy.sh

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

Sampel Bekerja setiap saat! Anda bahkan harus dapat menggunakan skrip untuk memecahkan masalah / men-debug setiap variabel env yang Anda mungkin merasa tidak disetel dll ... juga argumen penanganan yang diteruskan ke ssh akan bekerja juga ..

Catatan: Praktik Terbaiknya untuk selalu MEMENUHI path untuk skrip, executable, dll. Di atas hanyalah sebuah contoh yang memungkinkan jalur default disetel untuk memanggil moo.sh dalam folder moo;)

Itu mudah .. Terima kasih telah memposting ..

Referensi: / etc / passwd format

NotAdmin Dave
sumber
Jawaban yang bagus, tetapi saya benar-benar tidak pernah menggunakan pengguna di server secara langsung, saya selalu sshke server, dan dengan jalur authorized_keys, script dipanggil dan kemudian koneksi berakhir. Bagaimana saya harus memodifikasi authorized_keysagar ini berfungsi?
Tomáš Blatný
Itu harus bekerja sama. Anda akan mengautentikasi melalui kunci dan selama shell disetel ke skrip untuk akun jarak jauh yang dimaksud dalam file / etc / passwd server jarak jauh yang akan dijalankan skrip tersebut. Saya akan menambahkan tangkapan layar ke posting saya segera.
NotAdmin Dave
1
@Tidak sabar menunggu buku Anda
Burgi
Terima kasih atas jawaban Anda, itu tidak menyelesaikan masalah saya, tetapi bagi saya yang paling menarik dan benar-benar menyelesaikan masalah lain yang saya miliki. Memberi Anda bounty, terima kasih lagi
Tomáš Blatný
4

The envperintah akan melihat melalui pengguna yang $PATHmenemukan executable pertama dari nama yang diberikan. Jadi, /usr/bin/env phpakan mencari file yang dapat dieksekusi dipanggil phpdi salah satu direktori di $PATHdari pengguna yang menjalankannya.

Dalam kasus Anda, itu hampir pasti karena ketika menjalankan perintah ssh, Anda tidak memulai shell penuh dan tidak benar-benar membaca file inisialisasi shell Anda. Anda dapat memeriksanya dengan menjalankan perintah ini (perhatikan tanda kutip tunggal):

ssh deployer@XXX.com 'echo $PATH'

Dan membandingkan output untuk apa yang Anda dapatkan jika Anda ssh [email protected]dan kemudian jalankan echo $PATH. Di sistem saya. sebagai contoh:

$ 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

Oleh karena itu, $PATHskrip Anda memiliki akses ketika dijalankan dengan ssh [email protected]tidak sama dengan ketika Anda masuk untuk mengujinya.

Bagaimanapun, solusi sederhananya adalah menggunakan jalur lengkap ke penerjemah alih-alih env. Kedua envdan jalur penuh memiliki mereka kelebihan dan kekurangannya tetapi, dalam kasus ini, jalan lebih aman:

#!/usr/bin/php
terdon
sumber
ITYM " perhatikan tanda kutip tunggal" tidak " tidak ".
dave_thompson_085
@ dave_thompson_085 memang saya lakukan, terima kasih.
terdon
Saya sebenarnya menggunakan path lengkap di mana-mana, seperti yang saya sebutkan dalam pertanyaan saya, kesalahan dilaporkan di dalam composer install perintah, yang jelas saya tidak bisa modifikasi. Juga $PATHok, seperti yang saya sebutkan dalam pertanyaan saya juga, saya memeriksa semua hal dengan menambahkannya ke dalam skrip dan menjalankan dari jarak jauh melalui login ssh. Juga saya tidak dapat memeriksa ssh [email protected] 'echo $PATH'seperti yang Anda sebutkan, karena login ssh saya terbatas hanya pada satu skrip, tetapi saya hovever mengeceknya ketika saya menambahkan $ PATH ke skrip itu (dinyatakan di atas) Bagaimanapun, terima kasih atas jawaban Anda, dan terima + 1 untuk menjelaskan envhal itu kepada saya
Tomáš Blatný
@ TomášBlatný yah, Anda menggunakan env di suatu tempat, atau Anda tidak akan melihat kesalahan itu. Saya tidak tahu komposer tetapi Anda mungkin harus menyalin atau menautkan php yang dapat dieksekusi ke direktori di jalurnya. Hal semacam ini sulit untuk di-debug karena ada begitu banyak hal yang masing-masing bergantung pada yang lain.
terdon
Itu benar, envsebenarnya disebut komposer dalam. Tetapi ini tidak menyelesaikan masalah, mengapa beberapa komponis memanggil lulus, dan beberapa tidak. Namun saya akan menyelidiki lebih lanjut dengan melihat kodenya. Terima kasih atas waktu Anda
Tomáš Blatný
2

Apakah mungkin yang bashmemerlukan reset ke tabel hash-nya?

Jika demikian, Anda dapat mencoba menambahkan hash -rsuatu tempat di skrip Anda, yang memaksa shell untuk melihat $PATHlagi daripada mengandalkan (mungkin kedaluwarsa) info dari tabel hash.

Saat dibutuhkan, hashbisa juga mengaktifkan shell untuk mengingat path ke executable yang diinstal di lokasi non-standar menggunakan -popsi, atau lupa path dengan -dopsi.

Sumber:

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

pesepakbola terbang
sumber
Ini tidak memecahkan masalah bagi saya, namun ini adalah pengetahuan yang baik, jadi saya menambahkan Anda +1
Tomáš Blatný
1

Sepertinya mungkin Anda perlu menambahkan php ke jalur Anda. Mencoba:

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

Anda mungkin juga ingin memeriksa di mana php Anda tinggal untuk memastikan bahwa jalur di sana benar. Mencoba:

which php
Jeramy
sumber
Yah ini bukan masalah, karena php -vkeluaran versi PHP yang benar dan versi composer --versionkeluaran komposer. Seperti yang saya katakan, masalah ada dalam satu perintah saja.
Tomáš Blatný
1

Jelas bahwa Anda memiliki masalah jalur karena skrip penerapan Anda tidak dapat menemukan hal-hal yang pasti ada di jalur saat Anda melakukan login ssh normal.

Hal pertama yang harus dilakukan untuk mengonfirmasi bahwa Anda memiliki masalah PATH adalah memperbarui skrip penyebaran Anda untuk mencatat keluaran envatau setidaknya echo $PATH. Saya menduga cara penulisan skrip penyebaran Anda, $ PATH tidak disetel seperti yang Anda harapkan. Output debug ini akan mengkonfirmasi / menolak teori saya.

Saya melihat tutorial yang Anda ikuti. Anda mungkin harus memastikan saat memperbarui command=menjadi command="/bin/sh /path/to/your/script..."jika Anda belum memastikan skrip Anda dijalankan oleh shell yang tepat.

Jika Anda memang memiliki masalah PATH, perbaikan cepat / kotor hanya untuk secara eksplisit mengatur PATH di awal skrip deploy Anda.

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

Penjelasan terperinci dan opsi lebih lanjut ...

Di linux ketika perintah dijalankan, mereka mewarisi lingkungan proses induknya.

Ketika Anda login sebagai pengguna normal melalui SSH ada hal-hal yang terjadi (seperti menjalankan / etc / bashrc / etc / profile ~ / .bash_profile ~ / .bashrc dll). Pada titik itu Anda mungkin telah memperbarui lingkungan proses Anda dengan melakukan hal-hal seperti export PATH="$PATH:~/mybin"dalam skrip tersebut. Sekarang setiap proses masa depan yang Anda jalankan akan mewarisi lingkungan Anda saat ini.

Menjalankan perintah alih-alih mendapatkan shell login berarti bahwa perintah dijalankan oleh daemon ssh dan akan mewarisi lingkungan proses daemon ssh ... yang kemungkinan berbeda dari lingkungan Anda sebagai pengguna yang masuk.

Halaman manual untuk kunci resmi mencakup apa yang terjadi setelah otentikasi. Mengenai lingkungan:

  1. Membaca file ~ / .ssh / environment, jika ada, dan pengguna diizinkan untuk mengubah lingkungannya. Lihat opsi PermitUserEnvironment di sshd_config (5).

Jadi tempat yang tepat untuk mengkonfigurasi lingkungan untuk proses adalah di ~/.ssh/environmentmana ~direktori home untuk pengguna yang diautentikasi untuk menjalankan perintah. Anda juga perlu memeriksa sshd_config Anda untuk memastikan PermitUserEnvironment diizinkan.

~/.ssh/environment Formatnya juga ditentukan di halaman manual tentu saja.

         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.

Cara alternatif untuk menentukan lingkungan tanpa menggunakan metode yang disebutkan di atas adalah dengan menggunakan environment="NAME=value"opsi dalam file Authorized_keys. Lihat halaman manual yang saya tautkan di atas untuk detailnya.

mattpr
sumber
Mengenai Without knowing exactly how you have setup your deploy script to run: dalam pertanyaan saya di awal, ada tautan, bagaimana saya mengaturnya (menggunakan ~/.ssh/authorized_keys. Terima kasih atas tipnya dengan memperbarui perintah, saya mencobanya, tetapi sayangnya tanpa perbedaan. Namun saya akan menyelidiki lebih lanjut dan mencoba kerang yang berbeda Harap terima +1 untuk gagasan itu.
Tomáš Blatný
Apakah Anda mencoba memperbarui skrip deploy Anda untuk mencetak $ PATH saat ini? Bisakah Anda memposting hasilnya? Jika tidak sesuai dengan yang Anda harapkan, maka Anda bisa mencoba mengatur PATH secara eksplisit seperti yang saya sarankan di awal skrip deploy Anda.
mattpr