`ssh <host>` adalah shell login, tetapi `ssh <host> <command>` tidak?

12

Saya perhatikan bahwa ketika saya menjalankan perintah langsung pada host SSH menggunakan ssh <host> <command>sintaks, saya melihat output .bashrctetapi bukan output .bash_profile(atau .profile).

Misalnya, jika saya menempatkan perintah berikut di bagian atas kedua file,

echo ${BASH_SOURCE[0]}

dan sumber secara manual .bash_profile(sumber mana .bashrcpada gilirannya), saya akan melihat

$ . .bash_profile
.bash_profile
.bashrc

Ini adalah output yang sama yang saya lihat jika saya masuk ke komputer ini dari jarak jauh melalui SSH, menggunakan ssh <host>bentuk perintah. (Dan jika saya menyimpan di .bash_profiletempat lain untuk sementara waktu, tak satu pun dari baris ini akan bergema.)

Namun, jika saya menjalankan perintah langsung pada mesin jarak jauh dengan ssh <host> <command>bentuk ssh, maka hasilnya akan terlihat seperti ini:

$ ssh <host> echo foo
/home/rlue/.bashrc
foo

Pemahaman saya adalah bahwa perbedaan antara .bash_profiledan .bashrcyang pertama adalah untuk shell login sedangkan yang terakhir adalah untuk shell non-login yang interaktif .

Saya telah menyimpulkan yang berikut ini:

  1. ssh <host>sumber saja .bash_profile, sementara
  2. ssh <host> <command>sumber saja .bashrc, yang artinya
  3. yang pertama adalah shell login dan yang terakhir tidak.

Apakah kesimpulan ini benar? Mengapa ssh <host> <command>diperlakukan sebagai shell non-login yang interaktif? Bukankah SSH masih masuk ke mesin jarak jauh untuk menjalankan perintah?

Ryan Lue
sumber
output dari .bashrc? File itu tidak seharusnya menghasilkan output apa pun. Output apa pun dari .bashrcdapat merusak semua alat menggunakan ssh sebagai transportasi mereka.
kasperd
Cukup adil. Dalam hal ini, beberapa baris masuk .bashrcmelemparkan kesalahan, sedangkan baris serupa .bash_profiletidak. Saya mengambil kesempatan untuk menyelidiki perbedaan sebelum memperbaiki garis yang menyinggung.
Ryan Lue

Jawaban:

12

OpenSSH (kemungkinan besar apa yang Anda jalankan) memutuskan apakah akan membuat shell login atau tidak, dan itu hanya berlaku jika Anda tidak menjalankan perintah tertentu. Dari man ssh:

 If command is specified, it is executed on the remote host instead of a
 login shell.

Jadi ini adalah pilihan implementasi untuk server ssh apakah ia ingin membuat shell login atau tidak, dan jika Anda memberikan perintah untuk menjalankannya, itu tidak.

Meskipun sshmelakukan login, jika Anda menjalankan perintah dan keluar, itu benar-benar jauh lebih mirip dengan membuat shell hanya untuk menjalankan perintah itu daripada untuk mendapatkan lingkungan login. Tampaknya, mengingat itu, bahwa orang-orang yang menulis OpenSSH memutuskan untuk memperlakukannya seperti tugas semacam itu.

Mereka membuat shell non-interaktif, non-login untuk mengeksekusi perintah, karena itulah semangat menjalankan perintah dalam konteks / shell lain. Namun, biasanya, cangkang non-interaktif tidak akan secara otomatis sumber ~/.bashrcyang jelas terjadi di sini. bashsebenarnya mencoba membantu kami di sini. Dari dokumen

Dipanggil oleh daemon shell jarak jauh

Bash mencoba menentukan kapan dijalankan dengan input standar yang terhubung ke koneksi jaringan, seperti ketika dijalankan oleh daemon shell jarak jauh, biasanya rshd, atau secure shell daemon sshd. Jika Bash menentukan sedang dijalankan dengan cara ini, ia membaca dan mengeksekusi perintah dari ~ / .bashrc, jika file itu ada dan dapat dibaca. Ini tidak akan melakukan ini jika dipanggil sebagai sh. Opsi --norc dapat digunakan untuk menghambat perilaku ini, dan opsi --rcfile dapat digunakan untuk memaksa file lain untuk dibaca, tetapi rshd atau sshd umumnya tidak memanggil shell dengan opsi-opsi itu atau membiarkannya ditentukan.

Eric Renouf
sumber
"... itu dieksekusi pada host jarak jauh alih-alih shell login." Saya tidak mendapatkan dikotomi ini. Apakah perintah dijalankan di host jarak jauh alih-alih di shell login , atau perintah dieksekusi di host jarak jauh, alih-alih shell login dieksekusi di sana? Jika yang pertama, bagaimana bisa ini / atau? (Bukankah biasanya keduanya? ) Jika yang terakhir, masih dieksekusi dalam konteks beberapa shell, bukan? (yang interaktif, non-login?) Jadi pertanyaan saya juga tentang semantik - apa artinya "shell login", dan mengapa OpenSSH dirancang untuk tidak membuat satu untuk satu perintah?
Ryan Lue
@RyanLue Perbedaan "rasa" dari masing-masing cangkang membuat tugas-tugas tertentu lebih mudah / lebih aman / dioptimalkan dll. Saat melakukan suatu sshmemang memerlukan login, para pelaksana rupanya memutuskan bahwa dalam keadaan tertentu, misalnya, memintanya untuk mengeksekusi perintah dan kembali, lakukan tidak perlu / mendapat manfaat dari langkah-langkah tambahan yang diambil oleh shell login, dan karenanya mereka melewatinya. Jadi memang ada shell yang berjalan, saya anggap sebagian besar untuk mengatur lingkungan, dan karena shell tidak akan diberikan kepada pengguna yang masuk, mereka memperlakukannya seolah-olah pengguna baru saja memulai shell baru untuk menjalankan itu command
Eric Renouf
"Jadi memang ada shell yang berjalan, saya sebagian besar mengira untuk mengatur lingkungan ..." <tapi saya hanya bereksperimen dengan ini, dan tampaknya ssh <host> <command>tidak mewarisi lingkungan dari setiap shell login yang ada. Misalnya, $ ssh <host> \$PATHmengembalikan jalur sebagaimana adanya tanpa sumber .bash_profile(atau .profile, seolah-olah) ... Dalam arti praktis, mengapa Anda ingin menghindari langkah itu?
Ryan Lue
"... para pelaksana rupanya memutuskan bahwa dalam keadaan tertentu, misalnya, memintanya untuk menjalankan perintah dan kembali, tidak perlu / mendapat manfaat dari langkah-langkah tambahan yang diambil oleh shell login, dan karenanya mereka mengabaikannya." <juga, secara khusus mencari klarifikasi / wawasan tentang pilihan desain ini. Saya mendefinisikan PATHdi saya .profile- bukankah itu persis hal yang Anda ingin dimuat sebelum menjalankan perintah sewenang-wenang pada host jarak jauh?
Ryan Lue
1
@RyanLue server Boks ssh membedakan penggunaan ssh yang berbeda dan dapat memberikan izin untuk masing-masing. Login jarak jauh, eksekusi jarak jauh, salinan jarak jauh, Mungkin ini membantu memahami mengapa Anda memiliki perilaku yang Anda gambarkan. Login jauh (penggunaan interaktif) mungkin terlalu banyak untuk ditanyakan dalam lingkungan keamanan tinggi. Openssh dapat dibatasi dengan menggunakan rbash / rksh dan 'logout' di .bash_profile, atau chroot.
bbaassssiiee
4

The mengapa perilaku ini terletak pada tingkat lebih rendah dari kerang: ssh host( "login shell" kasus) menggunakan pseudoterminal pada remote host, untuk berkomunikasi antara sshdproses server dan shell; ssh host commandmenggunakan pipa di antara sshddan command, sebagai gantinya. Pseudoterminals diperlukan untuk menggunakan interpreter perintah secara interaktif, seperti shell, atau mode " read-eval-print " dari bahasa scripting; mereka mengimplementasikan banyak fitur ramah-manusia seperti mampu mundur mundur dari kesalahan ketik. Tetapi mereka memiliki lebih banyak overhead dan (tergantung pada konfigurasi) tidak mengizinkan data sewenang-wenang untuk melewati yang tidak dimodifikasi, jadi SSH menghindari menggunakannya ketika interaksi tidak akan terjadi.

Kadang-kadang perintah SSH / tidak ada perintah heuristik mendapatkan ini salah; itu bisa diganti dengan -tdan -Tswitch. Misalnya, untuk masuk ke mesin jarak jauh dan segera memasang kembali screensesi yang ditangguhkan , yang perlu Anda lakukan ssh -t host screen -R; ssh host screen -Rakan menyebabkan screenpengaduan tentang tidak terhubung ke terminal. Saya tidak bisa memikirkan situasi ketika Anda benar-benar ingin menggunakannya -T, tetapi ada di sana jika Anda pernah menemukannya.

zwol
sumber
1

Pertama, Anda perlu melihat berbagai jenis, Anda dapat membaca ini:

/unix/170493/login-non-login-and-interactive-non-interactive-shells

Sekarang jika Anda membuka bashrc Anda, Anda akan melihat di awal ini:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Itu berarti tergantung pada bagaimana Anda mengakses sistem file ini memuat kode di dalamnya atau tidak.

Genaro Morales
sumber
Oke, tetapi ini menimbulkan pertanyaan yang menarik: .bashrcboleh ditulis agar tidak bersumber jika itu disebut dalam konteks non-interaktif ( yaitu, jika tidak ada "pernyataan cepat" / $PS1variabel). Tetapi ssh <host> <command> jelas tidak interaktif ; artinya, itu tidak memunculkan prompt perintah. Jadi mengapa OpenSSH dirancang untuk membuat non-login, prompt interaktif (yang mencoba mencari sumber .bashrc) untuk case use yang tampaknya login dan non-interaktif ini ??
Ryan Lue