Bagaimana Anda mendapatkan layar untuk terhubung secara otomatis ke ssh-agent saat ini ketika melampirkan kembali ke layar yang ada?

48

Jika Anda memulai sesi layar saat ssh-agent sedang berjalan (dari ssh-forwarding agen), mengakses ssh-agent berfungsi dengan baik. Namun, jika Anda melepaskan diri dari sesi itu, keluar, masuk lagi (dengan penerusan ssh-agent), dan pasang kembali ke sesi layar Anda, akses ssh-agent tidak berfungsi.

Bagaimana ini bisa diperbaiki?

Der Hochstapler
sumber

Jawaban:

41

1) Dalam skrip rc SSH Anda (~ / .ssh / rc), Anda akan mengatur tautan simbolis dari lokasi kanonik ke SSH_AUTH_SOCK "saat ini". Inilah cara saya melakukannya di bash (konten ~ / .ssh / rc):

#!/bin/bash
if test "$SSH_AUTH_SOCK" ; then
    ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi

(dan pastikan untuk chmod 755 ~ / .ssh / rc). "Tes" hanya untuk mencegah kesalahan menampilkan jika Anda tidak menjalankan ssh-agent (yaitu Anda ssh tanpa -A). Bagian kedua dari perintah itu mengatur symlink di lokasi kanonik yang memperbarui dirinya ke SSH_AUTH_SOCK "asli" pada saat masuk. Ini independen dari menggunakan shell di ssh atau langsung memanggil perintah, berfungsi juga dengan "ssh -t screen -RRD".

Catatan: keberadaan ~ / .ssh / rc mengubah perilaku sshd. Khususnya, itu tidak akan memanggil xauth. Lihat man sshd untuk informasi lebih lanjut, dan cara memperbaikinya.

Selain itu, Anda tidak boleh menggunakan "-v" dengan ln segera setelah itu akan memecah rsync-over-ssh dengan diagnostik berikut:

$ rsync -n addr.maps.dev.yandex.net: .
protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(173) [Receiver=3.0.7]

2) Di .screenrc Anda, Anda hanya perlu mengganti SSH_AUTH_SOCK ke lokasi kanonik:

setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

Perhatikan bahwa Anda menggunakan setenv tidak peduli apa shell yang Anda gunakan; Saya pikir setenv adalah sintaks layar, bukan shell.

Solusi awalnya diadaptasi dari pos ini , yang tidak berfungsi, tetapi memiliki ide yang tepat.

apinstein
sumber
Ini mengasumsikan bahwa Anda pertama kali login, lalu mulai layar. Baik?
innaM
1
Bagaimana bisa dengan cara lain? Bagaimana Anda memulai layar tanpa login?
1
Kamu benar. Pertanyaan itu diungkapkan dengan cara yang bodoh. Tetapi Anda perlu login, memulai shell dan dari sana mulai layar? Saya sering melakukan sesuatu seperti "ssh -t some.machine screen -R".
innaM
1
Ah baiklah. Yah, saya baru saja mencoba ini dan itu tidak berhasil (yaitu ssh-agent tidak terhubung). Saya kira ssh tidak mengatur soket yang sesuai saat digunakan dalam mode ini. Mungkin argumen-foo lagi bisa membersihkan itu?
SSH memang mengatur soket, hanya saja tidak pernah memulai shell. Tetapi tip ini sangat berguna sehingga saya pikir saya mungkin mengubah kebiasaan saya saja.
innaM
23

Saya pikir ini berfungsi sebagai penyederhanaan jawaban @ sandip-bhattacharya. Masukkan ini di ~/.bashrcfile Anda , dan jalankan perintah ekspor di sesi layar yang sedang berjalan.

if [ -S "$SSH_AUTH_SOCK" ] && [ ! -h "$SSH_AUTH_SOCK" ]; then
    ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock

Bunyinya "jika $SSH_AUTH_SOCKsoket ( -S) dan bukan tautan simbolik ( ! -h), buat tautan simbolik baru di jalur yang diketahui. Dalam semua kasus, tentukan ulang SSH_AUTH_SOCKuntuk menunjuk ke jalur yang dikenal.

The ! -hMenghindari menciptakan referensi melingkar jika Anda menjalankan ini beberapa kali.

Juga, jika Anda menggunakannya byobu, ini dilakukan secara otomatis, tanpa perlu mengedit file konfigurasi.

Satu-satunya bug yang saya temukan dalam ini ( byobumemilikinya juga) adalah jika Anda membuka satu detik ssh -Aatau ForwardAgentkoneksi itu akan menimpa soket pertama, dan jika Anda menutup koneksi kedua sebelum yang pertama, Anda akan kehilangan satu-satunya soket yang baik.

Collin Anderson
sumber
1
Ini juga berfungsi untuk tmux.
Dag Høidahl
Berfungsi bagus, tetapi rusak saat menggunakan folder rumah yang dipasang dari jarak jauh. Dalam hal ini, gunakan ~/.ssh/ssh_auth_sock_"$(hostname)"untuk symlink Anda. Ini akan menjaga soket auth terpisah untuk setiap host.
Kibber
4

"ssh -t some.machine screen -R" tidak akan menjalankan bash dan karenanya tidak akan menjalankan skrip .bash_profile tempat symlink dibuat.

Anda dapat mencoba: ssh -t some.machine bash -c "screen -R"

(dengan asumsi Anda menggunakan bash sebagai shell Anda tentu saja)

Sunting: "Jawaban" itu sebenarnya adalah komentar atas jawaban pertama yang diberikan di atas :)

Komunitas
sumber
"Jawaban pertama yang diberikan di atas" tidak berarti apa-apa karena urutan jawaban berubah seperti yang dipilih dll. Sertakan tautan berbagi dari jawaban yang Anda maksud, karena itu tidak akan berubah.
rjmunro
3

Saya pikir Anda perlu autossh. Saya telah menggunakannya selama bertahun-tahun sekarang, dan dikombinasikan dengan layar membuat semua sesi terminal saya sepenuhnya portabel dan transparan. Saya cukup tutup lappy, pindah ke lokasi baru, buka lappy dan semua layar saya dan layar bersarang terhubung secara otomatis. Aku bahkan tidak memikirkannya lagi.

http://www.linux.com/archive/feature/134133

adalah dasar-dasarnya ... Saya membuat skrip lil untuk mengotomatiskan proses di .screenrc saya untuk host yang diberikan. (juga melakukan ssh forwarding saya, jadi di semua tempat yang berbeda ini saya dapat melakukan tunnel koneksi saya melalui server saya)

di distro autossh harus ada program yang disebut rscreen (dan .. ada!)

#!/bin/sh                                                                       
#
# sample script to use autossh to open up a remote screen
# session, or reconnect to an existing one. 
#
# $Id: rscreen,v 1.4 2002/05/07 17:54:13 harding Exp $
#
if [ "X$1" = "X" ]; then
    echo "usage: `basename $0` <host>"
    exit 1
fi

if [ "X$SSH_AUTH_SOCK" = "X" ]; then
    eval `ssh-agent -s`
    ssh-add $HOME/.ssh/id_rsa
fi

#AUTOSSH_POLL=600
#AUTOSSH_PORT=20000
#AUTOSSH_GATETIME=30
#AUTOSSH_LOGFILE=$HOST.log
#AUTOSSH_DEBUG=yes 
#AUTOSSH_PATH=/usr/local/bin/ssh
export AUTOSSH_POLL AUTOSSH_LOGFILE AUTOSSH_DEBUG AUTOSSH_PATH AUTOSSH_GATETIME 

autossh -M 20004 -t $1 "screen -e^Zz -D -R"

Ini seharusnya membantu masalah ssh / layar

Akhirnya, untuk menjaga ssh-agent saya tetap berjalan, saya menggunakan gantungan kunci, karena saya semacam kepala shell ... Saya pikir OSX memiliki sesuatu yang tersedia untuk menjaga agen Anda tetap ada ...

chiggs
sumber
2

Inilah metode yang saya gunakan:

SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK) ; eval $SOCK ; export SSH_AUTH_SOCK
DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY) ; eval $DISP ; export DISP

Saya biasanya mengatur alias atau fungsi shell dengan perintah tesis:

function ssh-screen-auth() {
  SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK)
  eval $SOCK
  export SSH_AUTH_SOCK
  DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY)
  eval $DISP
  export DISPLAY
}

Anda mungkin harus menyesuaikan ' layar - (r | DR) ' ekspresi reguler ke perintah persis yang Anda gunakan untuk memasang kembali layar Anda.

  • Baris pertama membaca variabel lingkungan SSH_AUTH_SOCK di ruang proses perintah " layar -r " yang baru saja Anda ketik dan memperbarui nilai di shell Anda saat ini.
  • Baris kedua diperlukan jika Anda menggunakan " ssh -X " untuk meneruskan koneksi X11: ini memperbarui variabel DISPLAY dengan cara yang sama.

Peringatan dengan metode saya: ada yang tidak beres jika ada perintah " layar " lain yang berjalan di komputer.

Farzy
sumber
-1 untuk penggunaan yang tidak perlu sudo.
0xC0000022L
1

Saya biasanya menjaga sesi jangka panjang (6+ bulan) berjalan di tempat kerja saya di server yang berbeda. Jadi berulang kali memasang kembali dan memiliki agen penerusan ssh yang layak telah bermasalah. Inilah yang saya atur di sistem saya:

if [ -z "${STY}" -a -t 0 -a X${USER} = Xmyusername ]; then
    reattach () {
        if [ -n "${SSH_AUTH_SOCK}" ]; then
            ln -snf "${SSH_AUTH_SOCK}" "${HOME}/.ssh/agent-screen"
            SSH_AUTH_SOCK="${HOME}/.ssh/agent-screen" export SSH_AUTH_SOCK
        fi
        exec screen -A -D -RR ${1:+"$@"} ;
    }

    screen -wipe
    echo 'starting screen... (type Cntl-C to abort)'
    sleep 5 && reattach
fi

Jika saya hanya masuk ke server jarak jauh tanpa memulai / memasang kembali layar, maka akan ada dua "soket", satu digunakan oleh screendan yang lain oleh shell baru. Seharusnya tidak ada dua sesi "startup", tetapi sesi kedua masih bisa mulai digunakan reattach -S new; dalam situasi ini, agen akan dibagikan dengan ~/.ssh/agent-screennilai. Untuk mendapatkan agen penerusan kembali, maka saya akan melepaskan, masuk kembali. X${USER} = XmyusernameMemastikan bahwa kode tidak akan dipanggil melalui sudopada server yang sama.

Arcege
sumber
1

Saya menggunakan variasi dari apa yang @apinstein gunakan untuk .bashrc saya .

case "$TERM" in
    screen)
           export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
        ;;
         *)
           if [[ -n "$SSH_AUTH_SOCK" ]]; then
               ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
           fi
        ;;
esac

Ini berfungsi untuk semua aplikasi yang berjalan di sesi layar saya. Ini akan bekerja untuk semua shell baru di sesi layar Anda. Untuk shell yang ada, Anda perlu menjalankan export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sockshell host untuk membuatnya bekerja.

PS Maaf untuk menambahkan ini sebagai jawaban independen, sedangkan itu hanya dibangun di atas jawaban @ apinstein. Harus melakukan ini karena komentar di stackoverflow tidak mendukung blok kode.

Sandip Bhattacharya
sumber
Kenapa tidak selalu symlink dan selalu ekspor?
Collin Anderson
@CollinAnderson Dua perilaku berbeda. satu di dalam shell layar, dan satu di dalam shell login biasa. variabel lingkungan di shell login diatur oleh ssh dan karenanya symlink ada. jika kita melakukan ini dalam sesi layar, maka kita akan menyebabkan loop symlink.
Sandip Bhattacharya
Ahh benar Anda hanya perlu menautkan jika $ SSH_AUTH_SOCK belum menjadi tautan. Lihat posting saya superuser.com/a/424588/134212
Collin Anderson
0

Saya mencoba liner sederhana ini seperti yang disarankan pada Mari membuat teman layar dan ssh-agent dan itu bekerja untuk saya.

Login Pertama Kali ke Target. Perlu dilakukan hanya sekali.

ssh -o StrictHostKeyChecking=no -C <userid>@<server>

Luncurkan Layar untuk pertama kalinya..perlu dilakukan hanya sekali.

eval `ssh-agent`; /usr/bin/screen -D -R -h 10000
ssh-add

Jika terlepas atau terputus, gunakan perintah ini untuk masuk selanjutnya untuk menghubungkan ke layar yang keluar.

ssh -o StrictHostKeyChecking=no -C -t <userid>@<server> ssh-agent /usr/bin/screen -D -R -h 10000
Sharjeel
sumber
0

Ini semua adalah jawaban yang sangat bagus. Saya melakukannya sedikit berbeda. Setelah saya memulai sesi ssh baru dan memasang kembali layar, saya mereset SSH_AUTH_SOCKvariabel lingkungan berdasarkan pada isi dari lingkungan root bash. Saya hanya memerlukan akses ssh-agent sesekali ketika saya menggunakan svn jadi saya hanya mengatur ulang SSH_AUTH_SOCKseperti yang diperlukan dalam shell ini.

Ini menggunakan sistem file proc begitu spesifik linux. Saya hanya menguji ini pada kotak linux tanpa kepala yang hanya diakses oleh saya, mungkin perlu beberapa penyesuaian untuk membuatnya bekerja di lingkungan lain.

Untuk mengatur ulang SSH_AUTH_SOCK (ini dapat dibuat sebagai alias).

$ . ~/bin/screen_auth.sh

screen_auth.sh terlihat seperti ini

# Find the pid of putty's bash shell
tty=`who | awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ { print substr($2, 5) }'`
pid=`ps -t $tty | grep bash | awk '{print $1}'`
# Find the SSH_AUTH_SOCK variable in its enviornment
auth_sock=`xargs --null --max-args=1 echo < /proc/$pid/environ | grep SSH_AUTH_SOCK`
eval "export $auth_sock"
iain
sumber
0

Semua solusi di atas menderita kondisi balap (baik dalam beberapa sesi SCREEN atau dalam beberapa koneksi SSH). Satu-satunya solusi universal yang dapat saya pikirkan adalah untuk pertama-tama mendorong SSH_AUTH_SOCK ke proses server SCREEN screen -rdan kemudian menariknya di dalam sesi BASH sebelum setiap perintah interaktif non-builtin. Sayangnya SCREEN dan BASH dirancang tanpa kesadaran akan masalah seperti itu, sehingga agak sulit untuk diterapkan dengan benar (meskipun tidak pernah terlambat untuk mengirim permintaan fitur ke kedua proyek). Upaya saya dilakukan untuk mengatasi masalah ini untuk sesi BASH yang dapat ditemukan di sini:

Untuk memasang:

  1. masukkan kedua skrip ke dalam $HOME/bin, tambahkan bit yang dapat dieksekusi;
  2. pastikan itu $HOME/binberjalan sebelum /usr/bindi PATH:

    PATH = $ HOME / bin: $ PATH

  3. tambahkan ini ke .bashrc:

    source $ HOME / bin / setup layar pembantu

Sekarang Anda dapat mencoba membuat sesi LAYAR di dalam sesi SSH, lepaskan, putuskan, sambungkan dan pasang kembali dan semoga ssh-add -lmenunjukkan kunci Anda dengan benar.

midenok
sumber
Perhatikan, ssh-agentdaemon permanen itu (seperti yang disarankan di sini superuser.com/a/412052/376867 ) tidak menderita kondisi balap, tetapi menderita keyring basi. Dan yang lebih penting, tidak terlalu aman untuk meninggalkan semua kunci Anda di host jarak jauh bersama dengan sesi layar (atau bahkan lebih lama sampai reboot jika ada tulisan yang disebutkan).
midenok
0

Saya membaca jawaban-jawaban lain dan tidak menemukan jawaban saya. Inilah yang saya gunakan. Buat file ~/.screenrc-wrapperdengan konten berikut:

escape ^xx
bindkey ^Ad detach

Dan tambahkan ini ke ~/.bashrc(atau ~/.zshrcjika Anda menggunakannya):

  if echo $TERM | grep -v 'screen' && ! screen -x -SU wrapper; then
      if echo $TERM | grep -v 'screen' && ! screen -x -SU main; then
      screen -c ~/.screenrc-wrapper -SU wrapper ssh-agent screen -SU main
      fi
  fi

Dengan cara ini Anda akan menggunakan dua sesi layar - satu adalah "pembungkus" dan satu adalah bagian dalam. Ini akan membuat yang terakhir tetap hidup bahkan ketika Anda logout dan itu akan tetap memiliki ssh-agent. Fitur bagus lainnya adalah ia akan mengingat pengaturan jendela Anda - jika Anda menggunakan split windows, ini mungkin sangat berguna.

Anda dapat menemukan fitur ini dalam konteks di dotfiles saya .

d33tah
sumber