Mengapa Bash tidak dapat menemukan perintah bahkan jika $ PATH ditentukan dengan benar?

9

Saya menentukan jalur ke perintah saya di file / etc / profile :

export PATH=$PATH:/usr/app/cpn/bin

Perintah saya terletak di:

$ which ydisplay 
/usr/app/cpn/bin/ydisplay

Jadi, ketika saya melakukan output "echo $ PATH" terlihat seperti:

$ echo $PATH
...:/usr/app/cpn/bin

Dan semuanya baik-baik saja, tetapi ketika saya mencoba meluncurkan perintah saya melalui SSH saya mendapatkan kesalahan:

$ ssh 127.0.0.1 ydisplay
$ bash: ydisplay: command not found

Tapi jalan saya masih ada:

$ ssh 127.0.0.1 echo $PATH
...:/usr/app/cpn/bin

Tolong jelaskan saya mengapa Bash tidak dapat menemukan ydisplay selama sesi SSH dan cara mengkonfigurasi SSH dengan benar untuk menghindari masalah ini.

Terlebih lagi, jika saya menetapkan $ PATH di file lokal .bashrc di pengguna saat ini semua berfungsi dengan benar. Tapi saya ingin memodifikasi hanya satu file, bukan menentukan banyak file untuk setiap pengguna. Inilah sebabnya saya bertanya.

SIGSEGV
sumber
1
apakah hanya menjalankan ydisplaypekerjaan? apakah ssh 127.0.0.1 /usr/app/cpn/bin/ydisplaybekerja?
Bananguin
@ user1129682 Ya, ydisplay dengan karya nama lengkap dan hanya karya ydisplay
SIGSEGV
Ketika Anda tidak login (Anda tidak memiliki sesi jarak jauh) tetapi hanya mengirim perintah dari jarak jauh Anda tidak memiliki akses ke variabel lingkungan dengan cara yang sama karena file .bashrc / .profile Anda tidak dijalankan. Ini adalah alasan karena mereka bertanggung jawab untuk mengatur variabel untuk sesi saat ini.
mnmnc
14
Hanya catatan: ssh 127.0.0.1 echo $PATHtidak melakukan apa yang Anda pikirkan: shell memperluas $ PATH bahkan sebelum ssh dieksekusi, sehingga tidak membuktikan atau menyangkal apa pun.
Ulrich Schwarz
2
pertanyaan stackoverflow ini mungkin bisa membantu
bsd

Jawaban:

5

tl; dr

Menjalankan ssh 127.0.0.1 ydisplaysumber ~/.bashrcdaripada /etc/profile. Ubah jalur Anda ~/.bashrcsebagai gantinya.

detail

Satu-satunya waktu /etc/profiledibaca adalah ketika shell Anda adalah "shell login".

Dari Manual Referensi Bash :

Ketika bash dipanggil sebagai shell login, ... pertama kali membaca dan mengeksekusi perintah dari file / etc / profile

Tetapi ketika Anda menjalankan ssh 127.0.0.1 ydisplay, bashtidak dimulai sebagai shell login. Namun ia membaca file startup yang berbeda. The Pedoman Bash Reference mengatakan:

ketika ... dieksekusi oleh ... sshd. ... itu membaca dan mengeksekusi perintah dari~/.bashrc

Jadi, Anda harus memasukkan PATHpengaturan Anda ~/.bashrc.

Pada sebagian besar sistem, ~/.bash_profilesumber ~/.bashrc, sehingga Anda dapat menempatkan pengaturan Anda hanya ~/.bashrcdaripada meletakkannya di kedua file.

Tidak ada cara standar untuk mengubah pengaturan untuk semua pengguna, tetapi kebanyakan sistem memiliki /etc/bashrc, /etc/bash.bashrc, atau serupa.

Gagal itu, atur pam_envdan masukkan PATHpengaturan /etc/environment.

Lihat juga:

Mikel
sumber
1

Secara historis, file profil ( /etc/profiledan ~/.profile) dipanggil ketika Anda masuk (pada konsol teks, apa lagi?) Dan melayani banyak tujuan:

  • Setel variabel lingkungan dan parameter lain (mis. Umask) untuk sesi tersebut.
  • Jalankan program tambahan di awal sesi (mis. Pemberitahuan email).
  • Jalankan program untuk sesi ini, jika berbeda dari shell (mis. Shell lain atau X Window).
  • Setel parameter terminal (mis stty .).
  • Setel parameter shell (mis. Alias).

Semua tujuan ini tidak diidentifikasi sebagai terpisah sampai nanti. Karena skrip profil dapat melakukan hal-hal yang hanya masuk akal dalam sesi interaktif (interaksi terminal, memulai program lain), ketika pemanggilan shell jarak jauh ( rsh ) diperkenalkan, merek rsh memutuskan untuk tidak memanggil shell jarak jauh sebagai shell login, sehingga skrip profil tidak dieksekusi. (Beberapa versi rshdmemiliki opsi untuk menjalankan shell jauh sebagai shell login.) Ssh menyalin perilaku ini untuk menjadi pengganti drop-in untuk rsh.

Jika Anda ingin skrip profil Anda dieksekusi, Anda dapat menjalankannya secara eksplisit.

ssh 127.0.0.1 '. /etc/profile; . ~/.profile; ydisplay'

Perhatikan perintah .untuk memuat skrip profil di dalam shell: mereka adalah perintah yang akan dieksekusi di dalam shell itu, bukan program eksternal.

Jika Anda ingin mengatur variabel lingkungan secara global untuk semua pengguna, ada metode lain pada banyak sistem: alih-alih mendefinisikannya /etc/profile, tentukan dalam /etc/environment. File ini dibaca melaluipam_env modul; kebanyakan distribusi Linux diatur untuk membacanya.

Jika shell login Anda adalah bash, ada kemungkinan lebih lanjut. Biasanya, Anda tidak boleh mengatur variabel lingkungan di.bashrc (karena mereka tidak akan diatur dalam sesi X kecuali jika Anda pergi melalui terminal dengan shell interaktif, karena mereka tidak akan diatur jika Anda masuk secara interaktif pada konsol teks atau lebih ssh, karena mereka akan mengesampingkan pengaturan khusus jika Anda menjalankan shell di dalam program lain). Namun, bash memiliki fitur aneh yang tidak pernah saya mengerti: bash dibaca ~/.bashrcdalam dua keadaan yang tidak terkait:

  • di shell interaktif yang bukan shell login;
  • di shell non-interaktif yang bukan shell login, jika bash mengira itu telah dipanggil oleh rshdatau sshd.

Ketika Anda menjalankan perintah di atas ssh, Anda berada dalam kasus kedua. Anda dapat mengatur agar profil Anda dibaca dengan membaca /etc/profiledan .profiledari .bashrc. Sertakan kode berikut dalam ~/.bashrc:

case $- in
  *i*) :;; # this is an interactive shell, fine
  *) # This is not an interactive shell! This must be a non-interactive remote shell session.
    . /etc/profile; . ~/.profile
    return;;
esac
Gilles 'SANGAT berhenti menjadi jahat'
sumber