คุณจะได้รับหน้าจอเพื่อเชื่อมต่อกับ ssh-agent ปัจจุบันโดยอัตโนมัติเมื่อติดกับหน้าจอที่มีอยู่อีกครั้งได้อย่างไร?


47

หากคุณเริ่มเซสชันหน้าจอขณะที่ ssh-agent กำลังทำงาน (จากการส่งต่อตัวแทน ssh -A) การเข้าถึง ssh-agent ทำได้ดี อย่างไรก็ตามหากคุณแยกออกจากเซสชันนั้นให้ออกจากระบบลงชื่อเข้าใช้อีกครั้ง (ด้วยการส่งต่อ ssh-agent) และแนบกับเซสชันหน้าจอของคุณอีกครั้งการเข้าถึง ssh-agent ไม่ทำงาน

จะแก้ไขได้อย่างไร?

คำตอบ:


41

1) ในสคริปต์ SSH rc ของคุณ (~ / .ssh / rc) คุณจะตั้งค่าลิงก์สัญลักษณ์จากตำแหน่งที่ยอมรับไปยัง "ปัจจุบัน" SSH_AUTH_SOCK นี่คือวิธีที่ฉันทำใน bash (เนื้อหาของ ~ / .ssh / rc):

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

(และตรวจสอบให้แน่ใจว่าได้รับ chmod 755 ~ / .ssh / rc) "การทดสอบ" เพียงเพื่อป้องกันข้อผิดพลาดไม่ให้แสดงหากคุณไม่ได้ใช้งาน ssh-agent (เช่นคุณ ssh ไม่มี -) ช่วงครึ่งหลังของคำสั่งนั้นตั้งค่า symlink ในตำแหน่งที่ยอมรับซึ่งจะปรับปรุงตัวเองเป็น "จริง" SSH_AUTH_SOCK ในเวลาล็อกอิน นี่เป็นอิสระจากการใช้เชลล์ใน ssh หรือเรียกใช้คำสั่งโดยตรงทำงานได้กับ "ssh -t screen -RRD"

หมายเหตุ: การมีอยู่ของ ~ / .ssh / rc จะเปลี่ยนพฤติกรรมของ sshd โดยเฉพาะอย่างยิ่งมันจะไม่เรียก xauth ดู man sshd สำหรับข้อมูลเพิ่มเติมและวิธีแก้ไข

นอกจากนี้คุณไม่ควรใช้ "-v" กับ ln ทันทีที่มันจะทำลาย rsync-over-ssh ด้วยการวินิจฉัยต่อไปนี้:

$ 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) ใน. screenrc ของคุณคุณเพียงแค่แทนที่ SSH_AUTH_SOCK ไปยังตำแหน่งที่ยอมรับได้:

setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

โปรดทราบว่าคุณใช้ setenv ไม่ว่าคุณจะใช้เชลล์อะไร ฉันคิดว่า setenv เป็นไวยากรณ์หน้าจอไม่ใช่เชลล์

โซลูชันดัดแปลงมาจากโพสต์นี้ซึ่งใช้งานไม่ได้ แต่มีแนวคิดที่ถูกต้อง


นี่ถือว่าคุณเข้าสู่ระบบครั้งแรกจากนั้นเริ่มหน้าจอ ขวา?
innaM

1
มันจะเป็นวิธีอื่นได้อย่างไร? คุณจะเริ่มหน้าจอโดยไม่ต้องลงชื่อเข้าใช้อย่างไร

1
คุณถูก. คำถามนั้นใช้ถ้อยคำที่โง่เขลา แต่คุณต้องเข้าสู่ระบบเริ่มเชลล์และจากหน้าจอเริ่มต้นหรือไม่ ฉันมักจะทำอะไรบางอย่างเช่น "ssh -t some.machine screen -R"
innaM

1
อาโอเค. ฉันเพิ่งลองทำสิ่งนี้และมันใช้งานไม่ได้ (เช่น ssh-agent ไม่ได้เชื่อมต่อ) ฉันเดา ssh ไม่ได้ตั้งค่าซ็อกเก็ตที่เหมาะสมเมื่อใช้ในแบบนี้ อาจจะมีอีกหลายข้อโต้แย้งที่จะทำความสะอาดที่?

SSH ทำการติดตั้งซ็อกเก็ตและไม่เคยเริ่มต้นเชลล์ แต่เคล็ดลับนี้มีประโยชน์มากจนฉันคิดว่าฉันอาจจะเปลี่ยนนิสัยของฉัน
innaM

23

ฉันคิดว่านี่เป็นคำตอบที่ง่ายของ @ sandip-bhattacharya วางสิ่งนี้ลงใน~/.bashrcไฟล์ของคุณแล้วเรียกใช้คำสั่งส่งออกในเซสชันหน้าจอที่กำลังทำงานอยู่

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

ที่อ่าน "ถ้า$SSH_AUTH_SOCKเป็นซ็อกเก็ต ( -S) และไม่ใช่ลิงก์สัญลักษณ์ ( ! -h) ให้สร้างลิงก์สัญลักษณ์ใหม่ที่เส้นทางที่รู้จักในทุกกรณีให้กำหนดใหม่SSH_AUTH_SOCKเพื่อชี้ไปที่เส้นทางที่รู้จัก

! -hหลีกเลี่ยงการสร้างการอ้างอิงแบบวงกลมถ้าคุณทำงานนี้หลายครั้ง

นอกจากนี้หากคุณใช้งานbyobuจะทำสิ่งนี้โดยอัตโนมัติโดยไม่จำเป็นต้องแก้ไขไฟล์ปรับแต่งใด ๆ

ข้อผิดพลาดเดียวที่ฉันพบในนี้ ( byobuมีเหมือนกัน) คือถ้าคุณเปิดที่สองssh -AหรือForwardAgentการเชื่อมต่อมันจะเขียนทับซ็อกเก็ตแรกและถ้าคุณปิดการเชื่อมต่อที่สองก่อนหน้าแรกคุณจะสูญเสียซ็อกเก็ตที่ดีเท่านั้น


1
ใช้งานได้tmuxดีเช่นกัน
Dag Høidahl

ใช้งานได้ดี แต่หยุดเมื่อใช้โฟลเดอร์บ้านที่เมาท์จากระยะไกล ในกรณีนี้ใช้~/.ssh/ssh_auth_sock_"$(hostname)"สำหรับ symlink ของคุณ มันจะเก็บซ็อกเก็ตรับรองความถูกต้องแยกต่างหากสำหรับแต่ละโฮสต์
Kibber

4

"ssh -t some.machine screen -R" จะไม่รัน bash และดังนั้นจะไม่เรียกใช้สคริปต์. bash_profile ที่มีการสร้าง symlink

คุณสามารถลอง: ssh -t some.machine bash -c "screen -R"

(สมมติว่าคุณใช้ bash เป็นเปลือกของหลักสูตร)

แก้ไข: "คำตอบ" นั้นจริงๆแล้วเป็นความเห็นเกี่ยวกับคำตอบแรกที่ให้ไว้ข้างต้น :)


"คำตอบแรกที่ให้ไว้ข้างต้น" ไม่ได้หมายความว่าอะไรเป็นคำสั่งเปลี่ยนแปลงคำตอบที่ได้รับการโหวตเป็นต้นโปรดรวมลิงค์แบ่งปันจากคำตอบที่คุณอ้างถึงเนื่องจากจะไม่มีการเปลี่ยนแปลง
rjmunro

3

ฉันคิดว่าคุณต้องการ autossh ฉันใช้มันมาหลายปีแล้วและเมื่อรวมกับหน้าจอทำให้เซสชันเทอร์มินัลทั้งหมดของฉันพกพาได้อย่างสมบูรณ์และโปร่งใส ฉันแค่ปิดเครื่องเลื่อนย้ายไปที่ตำแหน่งใหม่เปิดเครื่องเปิดและหน้าจอทั้งหมดของฉันและหน้าจอแบบซ้อนจะเชื่อมต่อโดยอัตโนมัติ ฉันจะไม่คิดถึงมันอีกต่อไป

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

เป็นพื้นฐาน ... ฉัน ruby'd สคริปต์ lil เพื่อทำให้กระบวนการใน. screenrc ของฉันเป็นอัตโนมัติสำหรับโฮสต์ที่กำหนด (เช่นเดียวกับการส่งต่อ ssh ของฉันดังนั้นในที่ต่าง ๆ เหล่านี้ฉันสามารถขุดอุโมงค์การเชื่อมต่อของฉันผ่านเซิร์ฟเวอร์ของฉัน)

ใน distro autossh ควรมีโปรแกรมที่เรียกว่า rscreen (และ .. มี!)

#!/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"

สิ่งนี้จะช่วยแก้ไขปัญหา ssh / หน้าจอ

ในที่สุดเพื่อให้ตัวแทนเอสเอสเอสของฉันทำงานฉันใช้พวงกุญแจเนื่องจากฉันเป็นประเภทของหัวเปลือกหอย ... ฉันคิดว่า OSX มีบางสิ่งบางอย่างที่สามารถทำให้ตัวแทนของคุณอยู่รอบ ๆ ...


2

นี่คือวิธีที่ฉันใช้:

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

ฉันมักจะตั้งค่านามแฝงหรือฟังก์ชั่นเปลือกด้วยคำสั่งวิทยานิพนธ์:

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
}

คุณอาจต้องปรับ ' หน้าจอนิพจน์ทั่วไป- (r | DR) ' ให้เป็นคำสั่งที่แน่นอนที่คุณใช้เพื่อติดตั้งหน้าจอของคุณใหม่

  • บรรทัดแรกอ่านตัวแปรสภาพแวดล้อมSSH_AUTH_SOCKในพื้นที่กระบวนการของคำสั่ง" screen -r " ที่คุณเพิ่งพิมพ์และอัพเดตค่าในเชลล์ปัจจุบันของคุณ
  • จำเป็นต้องใช้บรรทัดที่สองหากคุณใช้ " ssh -X " เพื่อส่งต่อการเชื่อมต่อ X11: เป็นการอัพเดตตัวแปรDISPLAYในลักษณะเดียวกัน

ข้อแม้กับวิธีการของฉัน: สิ่งต่าง ๆ อาจผิดปกติหากมีคำสั่ง " หน้าจอ " อีกชุดทำงานอยู่ในคอมพิวเตอร์


-1 sudoสำหรับการใช้งานที่ไม่จำเป็นของ
0xC0000022L

1

ฉันมักจะรักษาเซสชันระยะยาว (6 เดือน) ที่ทำงานของฉันบนเซิร์ฟเวอร์ที่แตกต่างกัน ดังนั้นการติดตั้งซ้ำและการมีตัวแทนการส่งต่อ ssh ที่ทำงานได้จึงเป็นปัญหา นี่คือสิ่งที่ฉันติดตั้งในระบบของฉัน:

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

ถ้าฉันเพิ่งเข้าสู่เซิร์ฟเวอร์ระยะไกลโดยไม่ต้องเริ่มต้น / หน้าจอการติดตั้งซ้ำจากนั้นจะมี "ซ็อกเก็ต" สองอันอันหนึ่งที่ใช้โดยscreenและอีกอันหนึ่งโดยเชลล์ใหม่ ไม่ควรมีสอง "เริ่มต้น" การประชุม แต่ช่วงที่สองจะยังคงได้เริ่มใช้reattach -S new; ในสถานการณ์นี้เอเจนต์จะถูกแชร์กับ~/.ssh/agent-screenค่า ในการรับเอเจนต์การส่งต่อที่ใช้งานได้กลับมาจากนั้นฉันจะแยกออกให้กลับเข้าสู่ระบบอีกครั้งX${USER} = Xmyusernameทำให้แน่ใจว่ารหัสจะไม่ถูกเรียกผ่านsudoบนเซิร์ฟเวอร์เดียวกัน


1

ฉันกำลังใช้รูปแบบของ @apinstein ที่ใช้สำหรับ. bashrcของฉัน

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

สิ่งนี้ใช้ได้กับแอพทั้งหมดที่ทำงานในเซสชันหน้าจอของฉัน สิ่งนี้จะใช้ได้กับเชลล์ใหม่ทั้งหมดในเซสชันหน้าจอของคุณ สำหรับเชลล์ที่มีอยู่คุณต้องรันexport SSH_AUTH_SOCK=~/.ssh/ssh_auth_sockบนโฮสต์เชลล์เพื่อให้ทำงานได้

ป.ล. ขออภัยที่เพิ่มคำตอบนี้เป็นคำตอบอิสระในขณะที่คำตอบของ @ apinstein เพิ่งสร้างขึ้น ต้องทำเช่นนี้เป็นความคิดเห็นใน stackoverflow ไม่สนับสนุนการบล็อกรหัส


ทำไมไม่เชื่อมโยงและส่งออกเสมอ
Collin Anderson

@CollinAnderson สองพฤติกรรมที่แตกต่าง ภายในหนึ่งเชลล์หน้าจอและอีกหนึ่งภายในเปลือกเข้าสู่ระบบปกติ ตัวแปรสภาวะแวดล้อมในล็อกอินเชลล์ถูกตั้งค่าโดย ssh และ symlink ที่นั่น หากเราทำสิ่งนี้ภายในเซสชันของหน้าจอจากนั้นเราจะทำให้ลูป symlink
Sandip Bhattacharya

อ่าใช่มั้ย คุณจะต้องเชื่อมโยงเฉพาะในกรณีที่ $ SSH_AUTH_SOCK ไม่ใช่ลิงก์ ดูโพสต์ของฉันsuperuser.com/a/424588/134212
Collin Anderson

0

ฉันลองใช้หนึ่งซับแบบง่ายตามที่แนะนำบนLet's สร้างหน้าจอและเพื่อน ๆ ของ ssh-agentและใช้งานได้สำหรับฉัน

การลงชื่อเข้าใช้ครั้งแรกสู่เป้าหมายต้องทำเพียงครั้งเดียว

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

เปิดหน้าจอเป็นครั้งแรก .. ต้องทำเพียงครั้งเดียว

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

หากแยกออกหรือยกเลิกการเชื่อมต่อให้ใช้คำสั่งนี้เพื่อเข้าสู่ระบบในภายหลังเพื่อเชื่อมต่อกับหน้าจอที่ออก

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

0

ทั้งหมดนี้เป็นคำตอบที่ดีจริง ๆ ที่ฉันทำแตกต่างออกไปเล็กน้อย หลังจากฉันเริ่มเซสชัน ssh และหน้าจอ reattach ใหม่ฉันรีเซ็ตSSH_AUTH_SOCKตัวแปรสภาพแวดล้อมตามเนื้อหาของสภาพแวดล้อมการทุบตีรูต ฉันต้องการการเข้าถึง ssh-agent เป็นครั้งคราวเมื่อฉันใช้ svn ดังนั้นฉันเพิ่งรีเซ็ตSSH_AUTH_SOCKตามที่ต้องการในเชลล์เหล่านี้

สิ่งนี้ใช้ระบบไฟล์ proc ดังนั้นจึงเป็นลินุกซ์ที่เฉพาะเจาะจง ฉันเพิ่งทดสอบสิ่งนี้บนกล่อง linux ที่ไม่มีหัวซึ่งเข้าถึงได้โดยฉันเท่านั้นมันอาจใช้เวลาปรับแต่งเพื่อให้สามารถใช้งานได้ในสภาพแวดล้อมอื่น

หากต้องการรีเซ็ต SSH_AUTH_SOCK (อาจเป็นนามแฝงได้)

$ . ~/bin/screen_auth.sh

screen_auth.sh มีลักษณะเช่นนี้

# 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"

0

โซลูชันทั้งหมดข้างต้นประสบกับสภาพการแข่งรถ (ไม่ว่าจะในหน้าจอหลายหน้าจอหรือในหลายการเชื่อมต่อ SSH) โซลูชันสากลเดียวที่ฉันนึกได้คือการผลัก SSH_AUTH_SOCK ไปที่ SCREEN เซิร์ฟเวอร์screen -rก่อนแล้วจึงดึงเข้าไปในเซสชัน BASH ก่อนแต่ละคำสั่งที่ไม่ใช่แบบบิลด์อินแบบโต้ตอบ น่าเสียดายที่ SCREEN และ BASH ได้รับการออกแบบโดยไม่ได้รับรู้ถึงปัญหาดังกล่าวดังนั้นจึงค่อนข้างยากที่จะนำไปใช้อย่างถูกต้อง (แม้ว่ามันจะไม่สายในการโพสต์คำขอคุณสมบัติไปยังโครงการทั้งสอง) ฉันพยายามที่จะเอาชนะปัญหานี้สำหรับเซสชัน BASH ซึ่งสามารถพบได้ที่นี่:

ติดตั้ง:

  1. ใส่สคริปต์ทั้งสองเข้าไป$HOME/binเพิ่มบิตที่สามารถเรียกใช้งานได้
  2. ตรวจสอบให้แน่ใจว่า$HOME/binไปก่อนหน้านี้/usr/binใน PATH:

    PATH = $ HOME / bin: $ PATH

  3. เพิ่มลงในของคุณ.bashrc:

    การตั้งค่า $ HOME / bin / screen-helper

ตอนนี้คุณสามารถลองสร้างเซสชัน SCREEN ในเซสชัน SSH ถอดแยกเชื่อมต่อและติดตั้งใหม่และหวังว่าssh-add -lจะแสดงคีย์ของคุณอย่างถูกต้อง


โปรดทราบว่าssh-agentภูตถาวร(ดังที่แนะนำที่นี่superuser.com/a/412052/376867 ) ไม่ได้รับผลกระทบจากสภาพการแข่งรถ แต่ต้องทนทุกข์ทรมานจากพวงกุญแจค้าง และที่สำคัญกว่านั้นคือมันไม่ปลอดภัยมากนักที่จะทิ้งกุญแจทั้งหมดไว้ที่รีโมตโฮสต์พร้อมกับหน้าจอเซสชัน (หรือนานกว่านั้นจนกว่าจะรีบูตในกรณีที่โพสต์ดังกล่าว)
midenok

0

ฉันอ่านผ่านคำตอบอื่น ๆ และหาของฉันไม่เจอ นี่คือสิ่งที่ฉันใช้ สร้างไฟล์ที่~/.screenrc-wrapperมีเนื้อหาดังต่อไปนี้:

escape ^xx
bindkey ^Ad detach

และเพิ่มสิ่งนี้ลงใน~/.bashrc(หรือ~/.zshrcถ้าคุณใช้สิ่งนั้น):

  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

วิธีนี้คุณจะใช้เซสชันสองหน้าจอ - อันใดอันหนึ่งคือ "wrapper" และอีกอันคือเซสชันภายใน สิ่งนี้จะช่วยให้ชีวิตหลังแม้ว่าคุณจะออกจากระบบและมันจะยังคงมีตัวแทน SSH อีกคุณสมบัติที่ดีคือมันจะจดจำการตั้งค่าหน้าต่างของคุณ - ถ้าคุณใช้ split windows มันอาจจะมีประโยชน์มาก

คุณสามารถค้นหาคุณลักษณะนี้ในบริบทของฉันdotfiles

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.