Ketika ssh'ing, bagaimana saya bisa mengatur variabel lingkungan di server yang berubah dari sesi ke sesi?

92

Ketika saya sshmasuk ke server, bagaimana saya bisa mengirimkan variabel lingkungan dari klien ke server? Variabel lingkungan ini berubah antara pemanggilan ssh yang berbeda jadi saya tidak ingin menimpa $HOME/.ssh2/environmentsetiap kali saya melakukan pemanggilan ssh. Bagaimana saya bisa melakukan ini?

Ross Rogers
sumber
2
Pertanyaan Anda harus sedikit lebih spesifik.
Ignacio Vazquez-Abrams
3
Pertanyaan itu cukup jelas bagi saya. Namun, dari sshhalaman manual, saya tidak melihat cara untuk melakukan itu selain mengatur variabel secara manual setelah Anda masuk ke server, kecuali jika Anda memodifikasi ~ / .ssh2 / environment.
garyjohn
Apakah itu variabel yang berbeda setiap kali? Atau nilai yang berbeda?
Dennis Williamson
1
Sebaliknya, karena ini sudah lebih populer. Tidak masalah itu lebih tua.
kenorb

Jawaban:

110

Tentu saja, Anda dapat mengatur variabel lingkungan di dalam perintah, namun Anda harus berhati-hati mengutip: ingat bahwa shell Anda akan mengurai baris perintah lokal Anda, dan kemudian shell remote akan mencoba-coba string itu. menerima.

Jika Anda ingin variabel mendapatkan nilai yang sama pada server yang dimilikinya pada klien, coba SendEnvopsi:

ssh -o SendEnv = MYVAR server.example.com perintah saya

Ini membutuhkan dukungan dari server. Dengan OpenSSH, nama variabel harus diotorisasi dalam /etc/sshd_config.

Jika server hanya mengizinkan nama variabel tertentu, Anda dapat mengatasinya; misalnya pengaturan umum memungkinkan LC_*melalui, dan Anda dapat melakukan hal berikut:

ssh -o SendEnv = LC_MYVAR server.example.com 'MYVAR = $ LC_MYVAR; batalkan LC_MYVAR; ekspor MYVAR; perintah saya

Bahkan jika LC_*bukan pilihan, Anda dapat meneruskan informasi dalam TERMvariabel lingkungan, yang selalu disalin (mungkin ada batas panjangnya). Anda masih harus memastikan bahwa shell jarak jauh tidak membatasi TERMvariabel untuk menunjuk tipe terminal yang dikenal. Lewati -topsi ke ssh jika Anda tidak memulai shell interaktif jarak jauh.

env TERM = "informasi tambahan: $ TERM" ssh -t server.example.com 'MYVAR = $ {TERM%: *}; TERM = $ {TERM ## *:}; ekspor MYVAR; perintah saya

Kemungkinan lain adalah mendefinisikan variabel secara langsung dalam perintah:

ssh -t server.example.com 'export MYVAR = "informasi tambahan"; perintah saya

Jadi, jika melewati variabel lokal:

ssh -t server.example.com 'ekspor MYVAR =' "'$ LOCALVAR'" '; perintah saya

Namun, waspadalah terhadap masalah mengutip: nilai variabel akan diinterpolasi langsung ke potongan shell yang dijalankan di sisi jarak jauh. Contoh terakhir di atas mengasumsikan bahwa $LOCALVARtidak mengandung tanda kutip tunggal ( ').

Gilles
sumber
2
Terima kasih banyak, saya marah karena variabel LC_ * bodoh diekspor pada ssh dan jawaban Anda mengarahkan saya ke mana harus mencari. Saya hanya perlu menonaktifkannya di ~ / .ssh / config
akostadinov
1
Saya berada dalam situasi poster asli, tetapi variabel yang saya inginkan diteruskan adalah TERM, jadi saya agak bingung dengan jawaban Anda. Apakah penerusan TERM otomatis ini telah dinonaktifkan oleh versi OpenSSH terbaru?
Keraguan
1
@ Keraguan Defaultnya adalah menolak semua variabel lingkungan di sisi server, dengan AcceptEnvarahan sshd_configsesuai yang diinginkan oleh administrator. Tetapi TERMdiperlakukan secara khusus, sejauh yang saya tahu tidak ada cara untuk memfilternya di sisi server (sudah diatur dalam lingkungan shell terlepas dari pengaturan konfigurasi). Apakah Anda yakin tidak ada skrip profil yang menimpanya (suka /etc/profileatau ~/.profileatau tidak ~/.bashrc)?
Gilles
2
@Gilles: Saya mengujinya lagi, dan kecuali saya secara eksplisit menambahkan JANGKA ke dalam arahan AcceptEnv saya, JANGKA tersebut tidak diteruskan. Saya tidak membuka shell, tetapi menjalankan perintah secara langsung, misalnya: "ssh -o SendEnv = TERM shell.example.com env". Itu mencetak semua variabel lingkungan, dan TERM hanya muncul jika itu di SendEnv pada klien dan AcceptEnv di server. Jika saya menjalankan "ssh -o SendEnv = TERM shell.example.com echo \ $ {TERM}" dengan semua AcceptEnv atau SendEnv, ia mencetak "bodoh", yang saya tidak yakin dari mana asalnya (env bahkan tidak daftar TERM dalam hal itu).
Doub
7
@ Keraguan Oh, begitu. TERMhanya dikirimkan jika klien meminta server untuk mengalokasikan tty. Jika tidak ada terminal di sisi jarak jauh, akan sia-sia mengirimkannya TERM. Saat Anda menentukan perintah, jika Anda ingin memiliki terminal di sisi jarak jauh, Anda memerlukan -topsi baris perintah (atau RequestTTYdalam ~/.ssh/config).
Gilles
12

Jika Anda dapat mengadministrasi host target Anda dapat mengkonfigurasi sshd untuk memungkinkan melewati variabel lingkungan lokal Anda ke host target.

Dari halaman manual sshd_config:

 PermitUserEnvironment
     Specifies whether ~/.ssh/environment and environment= options in
     ~/.ssh/authorized_keys are processed by sshd.  The default is
     "no".  Enabling environment processing may enable users to bypass
     access restrictions in some configurations using mechanisms such
     as LD_PRELOAD.

konfigurasi sshd biasanya hidup di /etc/ssh/sshd_config

Duncan Beevers
sumber
7
Sangat berguna untuk mengetahui bahwa ini diatur ke "tidak" secara default!
jathanism
6

Jadi, pada klien Anda, Anda memiliki beberapa variabel lingkungan, dan Anda ingin itu tersedia untuk perintah jarak jauh? Saya tidak berpikir ada cara agar ssh secara ajaib meneruskannya, tetapi Anda mungkin dapat melakukan sesuatu seperti ini. Alih-alih menggunakan, katakan:

ssh remote.host my_command

Kamu bisa melakukan ini:

ssh remote.host env ENV_VAR=$ENV_VAR my_command
pioto
sumber
"mungkin"? Saya berharap saya membacanya sebelum benar-benar mencoba jawaban ini. Tidak bekerja untuk saya.
tishma
1
Ingin menguraikan setiap kesalahan yang diterima, dll?
pioto
1
@pioto Mungkin mengutip, misalnya jika ENV_VAR memiliki spasi di dalamnya
Martin C. Martin
Pada Mac Anda harus memiliki opsi -t untuk versi interaktif, jika tidak, ia terlihat macet. Jadi ini mungkin berhasil: $ ssh -t remote.host env ENV_VAR = $ ENV_VAR my_command
muenalan
3

Tanggapan @ emptyset (yang tidak berhasil untuk saya) mengarahkan saya ke jawaban ini:

Anda dapat menambahkan perintah ini ke ~/.ssh/authorized_keysfile Anda :

command="/usr/bin/env VARIABLE=<something> $SHELL" ssh-rsa <key>

export VARIABLE=<something>segera keluar, dan koneksi SSH ditutup (mengunci saya keluar dari server), sedangkan /usr/bin/env ... $SHELLakan menjalankan shell default Anda dengan lingkungan yang dimodifikasi.

madprog
sumber
Ini hanya hang ketika masuk untuk saya. Ketika saya menghapusnya SSH kembali normal dan saya mendapatkan shell login yang biasa.
Nick Sweeting
@NickSweeting apakah Anda sudah mencoba mengganti $SHELLdengan shell yang sebenarnya? Juga periksa bahwa / usr / bin / env ada di server. Namun solusinya tidak sempurna: Saya perhatikan itu menggantung ketika saya ingin menggunakan scpatau perintah inline.
madprog
Ya, itu adalah hal pertama yang saya coba. Sayangnya tidak pernah berhasil, akhirnya mengaktifkan PermitUserEnvironment yesdan menggunakan, environment="..."bukan command="...".
Nick Sweeting
Ini bekerja dengan baik untuk saya.
Tn. Tao
3

Pada klien lokal Anda, ~/.ssh/configAnda dapat menambahkan SetEnv, misalnya

Host myhost
  SetEnv FOO=bar

Catatan: Periksa man ssh_config.

Kemudian di server, pastikan untuk mengizinkan klien melewati variabel lingkungan tertentu di /etc/ssh/sshd_configfile konfigurasi Anda :

AcceptEnv LANG LC_* FOO BAR*

Catatan: Periksa man sshd_config.

kenorb
sumber
1

Anda dapat mencoba menjalankan perintah khusus, dengan asumsi Anda memiliki pengaturan login ssh tanpa kata sandi. Di server, edit entri ~ / .ssh / otor_keys Anda yang terkait dengan kunci dari klien Anda:

command="export VARIABLE=<something>" ssh-rsa <key>

Lihatlah tautan ini di bagian Perintah Paksa untuk sedikit lebih detail.

emptyset
sumber
1
Saya mencoba ini, tetapi tidak berhasil. Itu menjalankan perintah dan keluar, jadi tidak ada sesi interaktif. Apakah itu perilaku normal? Jika demikian, itu bisa berguna jika semua yang ingin Anda lakukan adalah mengizinkan kunci spesifik untuk memicu perintah tertentu, tetapi jika Anda ingin meneruskan info yang digunakan dalam suatu sesi (seperti yang dinyatakan dalam pertanyaan) maka tidak ada gunanya untuk tujuan itu . Tidak ada sesi.
iconoclast
1

Saya membuat custom build dari OpenSSH untuk perangkat dengan cramfs di direktori home dan / etc (Cram FS adalah read-only) jadi ~ / .ssh / lingkungan tidak akan berfungsi tanpa membangun kembali seluruh FS dan ini adalah lapangan yang digunakan perangkat (Sistem Tertanam Oleh karena itu penggunaan CRAMFS). Anda dapat menentukan di sshd_config lokasi file authroized_keys tetapi karena alasan tertentu environment = hanya berfungsi untuk variabel lingkungan di ~ / .ssh / authroized_keys. Mengedit / etc / profile bukan pilihan dan saya harus memuat ssh di direktori non-standar. Dalam session.c setelah child_set_env (... "MAIL" ...) cukup tambahkan variabel lingkungan yang Anda butuhkan (Ini adalah hack yang saya tahu ...) tetapi hanya memetikan seseorang membutuhkan beberapa env hardcoded untuk sesi jika Anda kompilasi dari sumber Anda dapat melakukan ini. TGI-FLOSS

Akan
sumber
0

hanya satu perintah sederhana:

ssh -t your_host_or_ip 'export some_var_name=whatever_you_want; bash'
grepit
sumber