sh file startup lewat ssh

10

Saya punya beberapa perintah penting yang perlu saya jalankan sebelum shell sh dimulai. Ini diperlukan untuk melewati perintah SSH di perintah SSH ( ssh host somecommand) dan program lain yang menjalankan perintah.

Dalam saya, .profilesaya punya ini:

ihammerhands@wreckcreations:~> cat .profile
#specific environment and startup programs
export PS1="\u@wreckcreations:\w> "
export PYTHONPATH=~/python/lib/python2.4/site-packages
export PATH=$PATH:~/bin:~/python/bin

Namun, ini gagal:

W:\programming\wreckcreations-site\test-hg>ssh name@host echo $PATH
Enter passphrase for key '/home/Owner/.ssh/id_rsa':
/usr/local/bin:/bin:/usr/bin

Perhatikan opsi PATH yang hilang

Apa nama yang tepat untuk profil sh? Catatan: Saya tidak memiliki akses root dan tidak ingin ini diterapkan ke pengguna lain. Apakah ada cara lain untuk melakukan ini?


EDIT: Tampaknya /bin/shtautan ke bash, yang tidak mengejutkan. Yang mengejutkan adalah bahwa profil saya masih diabaikan. Ada saran?

TheLQ
sumber
1
Saya merasa tidak ingin mengulangi apa yang ada di halaman manual, jadi lihat saja halaman manual bash di bawah bagian 'INVOKASI'. Itu dekat bagian atas dan menjelaskan semua yang perlu Anda ketahui.
camh
Anda dapat mencoba menggunakan ssh name@host -t echo $PATH.
Gert
@Gert Output sama
TheLQ
@camh Apakah Anda pikir saya akan menanyakan pertanyaan ini jika saya belum memeriksa halaman manual? Saya sudah membacanya berkali-kali + posting lain tetapi tidak pernah bisa menemukan jawaban untuk masalah khusus ini, karena saya tidak yakin di mana perintah ssh tahap dan perintah program lain dieksekusi di
TheLQ
1
@TheLQ: Saya tidak kenal Anda jadi saya tidak tahu apakah Anda akan memeriksa halaman manual. Yang saya tahu adalah bahwa jawabannya ada di sana, jadi alih-alih mengulanginya kata demi kata, saya mengarahkan Anda ke sana. Pointer yang lebih spesifik adalah mencari kerang non-interaktif karena itulah skenario ssh Anda. Jika sesuatu di halaman manual tidak jelas, mungkin Anda dapat mengajukan pertanyaan yang lebih spesifik.
camh

Jawaban:

8

Tampaknya perlu dicatat bahwa perintah yang Anda sebutkan dalam pertanyaan Anda

ssh name@host echo $PATH

akan sangat berguna. Substitusi variabel untuk $ PATH dilakukan oleh shell lokal Anda, dan diteruskan ke ssh yang mengeksekusi gema pada sistem jarak jauh untuk mencetak konten variabel path, karena diperluas pada sistem lokal Anda. Ini adalah contoh saya melakukan sesuatu yang serupa antara Mac saya dan mesin Linux di jaringan saya:

LibMBP:~ will$ echo $PATH
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren echo $PATH
will@warren's password: 
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren 'echo $PATH'
will@warren's password: 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
LibMBP:~ will$ 

Perhatikan bagaimana saya perlu menggunakan tanda kutip untuk mencegah shell lokal saya memperluas variabel.

wrosecrans
sumber
Di Windows Cygwin land, tanda kutip tunggal tidak melakukan apa pun di Cygwin atau Command prompt. Anehnya, tanda kutip ganda membuat PATH berkembang sepenuhnya ke mesin lokal saya di Cygwin. Jadi, apa pun yang diberikan ssh kepada saya bukan jalur saya, ini adalah milik server
TheLQ
@TheLQ Kutipan tunggal diperlukan pada prompt unix (termasuk Cygwin), tetapi Anda tidak perlu tanda kutip pada prompt cmd.
Gilles 'SO- stop being evil'
12

~/.profilehanya dieksekusi oleh shell login. Program yang memanggil shell memutuskan apakah shell akan menjadi shell login (dengan menempatkan -sebagai karakter pertama dari argumen zeroth pada permintaan shell). Ini biasanya tidak dieksekusi ketika Anda masuk untuk menjalankan perintah tertentu.

OpenSSH secara khusus memanggil shell login hanya jika Anda tidak menentukan perintah. Jadi, jika Anda menentukan perintah, ~/.profiletidak akan dibaca.

OpenSSH memungkinkan pengaturan variabel lingkungan di sisi server. Ini harus diaktifkan dalam konfigurasi server , dengan PermitUserEnvironmentarahan. Variabel dapat diatur dalam file ~/.ssh/environment. Dengan asumsi Anda menggunakan otentikasi kunci publik, Anda juga dapat mengatur variabel per-kunci di ~/.ssh/authorized_keys: tambahkan environment="FOO=bar"di awal baris yang relevan.

Ssh juga mendukung pengiriman variabel lingkungan. Di OpenSSH, gunakan SendEnvarahan dalam ~/.ssh/config. Namun variabel lingkungan spesifik harus diaktifkan dengan AcceptEnvarahan dalam konfigurasi server, jadi ini mungkin tidak berhasil untuk Anda.

Satu hal yang saya pikir selalu berfungsi (cukup aneh) selama Anda menggunakan otentikasi kunci publik adalah (ab) menggunakan command=opsi dalam authorized_keysfile . Kunci dengan commandopsi hanya baik untuk menjalankan perintah yang ditentukan; tetapi perintah dalam authorized_keysfile berjalan dengan variabel lingkungan SSH_ORIGINAL_COMMANDdiatur ke perintah yang ditentukan pengguna. Variabel ini kosong jika pengguna tidak menentukan perintah dan karenanya mengharapkan shell interaktif. Jadi Anda dapat menggunakan sesuatu seperti ini di ~/.ssh/authorized_keys(tentu saja, itu tidak akan berlaku jika Anda tidak menggunakan kunci ini untuk otentikasi):

command=". ~/.profile; if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then eval \"$SSH_ORIGINAL_COMMAND\"; else exec \"$SHELL\"; fi" ssh-rsa 

Kemungkinan lain adalah menulis skrip wrapper di server. Sesuatu seperti yang berikut ini di ~/bin/ssh-wrapper:

#!/bin/sh
. ~/.profile
exec "${0##*/}" "$@"

Kemudian membuat link simbolik ke script ini disebut rsync, unison, dll Lulus --rsync-path='bin/rsync'pada rsyncbaris perintah, dan sebagainya untuk program lain. Sebagai alternatif, beberapa perintah memungkinkan Anda untuk menentukan potongan seluruh shell untuk dijalankan dari jarak jauh, yang memungkinkan Anda untuk membuat perintah lengkap: misalnya, dengan rsync, Anda dapat menggunakan --rsync-path='. ~/.profile; rsync'.

Ada jalan lain yang tergantung pada shell login Anda menjadi bash atau zsh. Bash selalu membaca ~/.bashrcketika dipanggil oleh rshd atau sshd, bahkan jika itu tidak interaktif (tetapi tidak jika itu disebut sebagai sh). Zsh selalu membaca ~/.zshenv.

## ~/.bashrc
if [[ $- != *i* ]]; then
  # Either .bashrc was sourced explicitly, or this is an rsh/ssh session.
  . ~/.profile
fi

## ~/.zshenv
if [[ $(ps -p $PPID -o comm=) = [rs]shd && $- != *l* ]]; then
  # Not a login shell, but this is an rsh/ssh session
  . ~/.profile
fi
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Bagaimana dengan perintah yang dijalankan oleh perintah lain? Dalam hal ini akan menjadi kait Mercurial. Mercurial perlu berada di jalur agar hook berpikir untuk bekerja
TheLQ
Gunakan salah satu teknik yang saya indikasikan untuk menjalankan profil Anda dalam perintah ssh noninteraktif. Salah satunya ( command=di authorized_keys) bekerja transparan. Yang lain memerlukan shell atau opsi tertentu dalam konfigurasi server ssh. Setara dengan Mercurial --rsync-pathadalah --remotecmd.
Gilles 'SO- stop being evil'
Mungkin bermanfaat bagi sebagian orang untuk memasukkan command=perintah lengkap yang sama seperti pada posting Anda superuser.com/a/207262/137762
mforbes
1

Biasanya saat login, bash membaca perintah dari:

~ / .bash_profile
~ / .bashrc

Dari halaman bash man:

~ / .bash_profile
File inisialisasi pribadi, dieksekusi untuk shell login

~ / .bashrc
File startup individu per-interaktif-shell

Alexander Pogrebnyak
sumber
0

Saya kehabisan waktu untuk menguji ini, tetapi melihat-lihat halaman manual yang saya temukan:

man bash: Ketika bash dimulai secara non-interaktif, untuk menjalankan skrip shell, misalnya, ia mencari variabel BASH_ENV di lingkungan, memperluas nilainya jika muncul di sana, dan menggunakan nilai yang diperluas sebagai nama file untuk baca dan eksekusi. Bash berperilaku seolah-olah perintah berikut dijalankan: if [-n "$ BASH_ENV"]; kemudian . "$ BASH_ENV"; tetapi nilai variabel PATH tidak digunakan untuk mencari nama file.

man ssh: ~ / .ssh / environment Berisi definisi tambahan untuk variabel lingkungan; lihat LINGKUNGAN, di atas.

Kombinasi tersebut menyarankan bagaimana Anda dapat menjalankan ssh. Profil Anda

Sayangnya server saya memiliki PermitUserEnvironment dengan nilai default tidak, yang membuat ini tidak bekerja untuk saya (dan seperti saya katakan saya tidak punya waktu untuk bermain lebih banyak dengannya).

kasterma
sumber
Bahkan jika saya bisa membuat SSH bekerja dengan secara eksplisit menyatakan beberapa variabel lingkungan di lingkungan, itu masih tidak akan membantu memperbaiki membuat profil saya dieksekusi ketika program lain memanggil perintah
TheLQ
Dalam contoh Anda, semua yang Anda lakukan adalah mengatur variabel lingkungan, apa lagi yang ingin Anda lakukan?
kasterma
0

(dihapus ... hanya dapat memiliki satu Hyperlink sebagai pengguna baru ~)

Memperbarui

Maaf, saya belum melihat bahwa ini tentang sesi non-interaktif, di mana tautan di atas tidak berlaku.

Ketika Bash mulai dalam mode kompatibilitas SH, ia mencoba untuk meniru perilaku startup versi historis sh sedekat mungkin, sambil menyesuaikan dengan standar POSIX® juga. File profil yang dibaca adalah / etc / profile dan ~ / .profile, jika itu adalah shell login.

Jika itu bukan shell login, variabel lingkungan ENV dievaluasi dan nama file yang dihasilkan diambil sebagai nama file startup.

Setelah file startup dibaca, Bash memasuki mode kompatibilitas POSIX (r) (untuk menjalankan, bukan untuk memulai!).

Bash dimulai dalam mode kompatibilitas ketika:

  • nama file dasar di argv [0] adalah sh (:!: Perhatian pengguna Linux uber-pintar ... / bin / sh mungkin ditautkan ke / bin / bash, tetapi itu tidak berarti itu bertindak seperti / bin / bash :! :)

Jadi pertanyaannya adalah, mengapa tidak menjalankannya, meskipun shell Anda dimulai seperti ini.

Sumber


sumber
Saya telah melihat tetapi seperti yang saya katakan kepada camh, saya tidak tahu di mana perintah stage ssh dan perintah program lainnya dijalankan. Saya sudah membaca halaman manual dan panduan lainnya berkali-kali
TheLQ