Mengapa $ PATH dari perintah ssh remote berbeda dari shell interaktif?

20

Saya memiliki pengguna yang tidak melakukan modifikasi pada $ PATH dalam file-file apa pun: ini persis dengan pengaturan default sistem. Dari shell login:

$ ssh example.com
user@example.com:~$ cat /tmp/hello.hs
#!/bin/bash

echo "$SHELL"
echo "$PATH"

user@example.com:~$ /tmp/hello.hs
/bin/bash
/usr/local/bin:/usr/bin:/bin

Persis seperti yang ditentukan dalam /etc/profile. Saya menemukan ini agak tidak terduga:

$ ssh example.com '/tmp/hello.sh'
/bin/bash       
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

Seperti yang saya katakan, tidak ada modifikasi $ PATH di ~/.bashrc, atau di /etc/bash.bashrc. Juga ~/.ssh/environmenttidak. Yang ssh(1)menyatakan bahwa variabel lingkungan PATHadalah

Setel ke PATH default, seperti yang ditentukan saat kompilasi ssh.

tapi thread ini dari StackOverflow dan ini mailing list artikel menyarankan bahwa saya harus bisa mempengaruhi $ PATH untuk perintah yang diberikan hanya dengan memodifikasi / etc / profile, salah satu file shell startup, dll

Apa yang terjadi di sini?

ikan troutwine
sumber

Jawaban:

16

Dari ssh(1)halaman manual: "Jika perintah ditentukan, itu dijalankan pada host jarak jauh, bukan shell login."

Jadi singkatnya ketika Anda benar-benar login ke bash mesin dimulai sebagai shell login dan memuat file yang sesuai, ketika Anda terhubung dari jarak jauh dan mengeluarkan perintah itu dijalankan di tempat bash, yang berarti bahwa file-file ini TIDAK memuat. Anda dapat mengatasinya dengan menggunakan su -l -catau serupa di bagian perintah ssh.

Dalam beberapa kasus saya telah melihat -targumen untuk ssh bekerja (mengalokasikan tty) juga.

Sunting 1 :
Saya pikir informasi PATH yang Anda temukan, bahwa jalur default (kecuali kita menimpanya) adalah yang dikompilasi ke sshd. Saya memastikan bahwa / etc / profile saya, / etc / bash *, dotfile lokal, dll. Tidak memiliki informasi PATH di dalamnya, kemudian saya masuk dan masih memiliki PATH. Saya mencari yang ini di sshd dan menemukannya di sana. Jadi begitulah cara manual mengatakan:

ahnberg@remote$ strings /usr/sbin/sshd | grep -i x11 | grep bin
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

Kemudian saya menambahkan PATH=$PATH:/my/testke bagian paling atas .bashrcfile saya di remote, dan periksa lagi:

ahnberg@local$ ssh ahnberg@remote "env | grep PATH"
PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/my/test

Jadi saya benar-benar dapat mempengaruhinya, dan PATH default adalah yang dikompilasi ke sshd. :)

Mattias Ahnberg
sumber
Hmm, frasa "dieksekusi pada host jarak jauh" berarti lebih banyak daripada yang dikatakannya, saya pikir. Bit yang lebih menarik, yang saya lewatkan sebelumnya, datang di bagian 'LINGKUNGAN' dari halaman yang sama: "PATH Set ke PATH default, seperti yang ditentukan saat mengkompilasi ssh." Kecuali ini menunjukkan bahwa saya harus dapat mempengaruhi PATH dari suatu perintah.
ikan trout
Yah intinya adalah itu bukan shell login sehingga tidak menjalankan / source / termasuk file startup dengan cara yang sama seperti untuk shell login, maka saran saya untuk mencoba. Menempatkan sesuatu .bashrcmungkin juga bekerja, tetapi secara keseluruhan saya akan mengatasinya jika PATH penting. Atau mengapa tidak menentukan nama path lengkap jika Anda memerlukan cara 'perintah' untuk menjalankan ssh? :)
Mattias Ahnberg
Saya sedikit mengedit posting saya. Sekarang, ada shell login, shell non-login dan varian interaktif / non-interaktif. Perintah SSH dipanggil dalam shell pengguna dalam bentuk non-login non-interaktif. The bash(1)Doa menunjukkan bahwa tidak ada file startup dibaca dalam mode ini, tapi saya tidak dapat menemukan dokumentasi di bagaimana ssh memohon shell. Ini tampaknya berlawanan dengan sumber yang ditautkan di atas, kecuali orang lain memiliki / etc / ssh / sshrc file startup yang tidak saya miliki. (Ada penyelesaian, tentu saja, tetapi intinya adalah memahami persis bagaimana Debian SSHD menangani jalur secara default.)
troutwine
Jika saya memodifikasi PATH di /etc/profilepembaruan jalur kotak jarak jauh untuk saya, maka ssh user@remotebox 'env'tunjukkan padaku PATH yang diperbarui. Hal yang sama berlaku jika saya menambah export PATH=$PATH:/my/testpath.bashrc (tetapi dalam kasus saya di atas file sebelum memeriksa kerang interaktif ( -z "$PS1").
Mattias Ahnberg
Diperbarui dengan tes / temuan saya.
Mattias Ahnberg
3

Saya bisa mendapatkan ssh untuk menjalankan perintah menggunakan jalur jarak jauh dengan menjalankan:

ssh dist@d6 "bash --login -c 'env'"

Di sini env dapat diganti dengan perintah apa pun yang Anda inginkan.

Saya memiliki kunci yang diotorisasi sehingga tidak perlu kata sandi untuk menjalankan perintah atau ssh.

Ian
sumber
3

Saya datang dengan solusi berbeda untuk memperbaiki masalah. Preferensi pribadi saya adalah membuat file konfigurasi baru alih-alih mengubah yang sudah ada. Dengan cara ini saya dapat lebih mudah menghapus perubahan dari konfigurasi default.

Berikut isinya /etc/profile.d/ssh_login.sh:

#!/bin/sh
if [ "$SSH_CONNECTION" ]; then
    echo "User '$USER' logged in from '${SSH_CONNECTION%% *}'"
    . /etc/environment
fi

Menggunakan dropbeardi tempat openssh-server(ini juga harus bekerja dengan openssh), variabel SSH_CONNECTION akan diatur secara otomatis ketika saya login jarak jauh. Saya membuat konfigurasi profil shell baru untuk mendeteksi login SSH, menampilkan beberapa informasi di layar dan, yang paling penting, memuat pengaturan lingkungan global dari /etc/environmentuntuk menggantikan nilai yang dikompilasi. Harap dicatat bahwa ini hanya memengaruhi shell SSH interaktif, bukan eksekusi perintah jarak jauh.

Atau , jika Anda menggunakan openssh dan selalu ingin memuat lingkungan global, terlepas dari apakah itu shell interaktif, Anda dapat menempatkan symlink ~/.ssh/seperti ini:

ln -s /etc/environment ~/.ssh/environment

Maka Anda perlu mengaktifkan PermitUserEnvironmentopsi di /etc/sshd/sshd_config. Hanya lakukan ini untuk pengguna tepercaya, karena ini dapat memungkinkan mereka untuk melewati pembatasan akses di beberapa konfigurasi menggunakan mekanisme seperti LD_PRELOAD. Silakan lihat man sshd_configuntuk informasi lebih lanjut, khususnya cara menggunakan Matchblok untuk membatasi opsi untuk pengguna / grup tertentu.

tachylatus
sumber
0

Jika Anda ingin jalur profil dimuat, coba:

#!/bin/bash -i

di bagian atas skrip. Dengan begitu shell berada dalam mode interaktif saat menjalankan skrip.

Ketika bash dipanggil sebagai shell login interaktif, atau sebagai shell non-interaktif dengan opsi --login, ia pertama kali membaca dan mengeksekusi perintah dari file / etc / profile, jika file itu ada. Setelah membaca file itu, ia mencari ~ / .bash_profile, ~ / .bash_login, dan ~ / .profile, dalam urutan itu, dan membaca serta mengeksekusi perintah dari yang pertama yang ada dan dapat dibaca. Opsi --noprofile dapat digunakan ketika shell mulai menghambat perilaku ini.

http://linux.die.net/man/1/bash

Adam Brand
sumber