Answers:
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(即不带-A的ssh),则“测试”只是为了防止显示错误。该命令的后半部分在规范位置设置符号链接,该符号链接在登录时将自身更新为“真实的” SSH_AUTH_SOCK。这与在ssh中使用shell或直接调用命令无关,也可以与“ ssh -t screen -RRD”一起使用。
注意:〜/ .ssh / rc的存在会更改sshd的行为。值得注意的是,它不会调用xauth。有关更多信息,以及如何解决此问题,请参见man sshd。
另外,您不应该在ln上同时使用“ -v”,因为它将通过以下诊断破坏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
请注意,无论使用哪种shell,都将使用setenv。我认为setenv是屏幕语法,而不是外壳。
我认为这可以简化@ 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
连接,它将覆盖第一个套接字,并且如果您在第一个套接字之前关闭第二个连接,则会丢失唯一的套接字。
tmux
。
~/.ssh/ssh_auth_sock_"$(hostname)"
您的符号链接。它将为每个主机保留单独的身份验证套接字。
“ ssh -t some.machine screen -R”将不会运行bash,因此不会运行在其中创建符号链接的.bash_profile脚本。
您可以尝试:ssh -t some.machine bash -c“ screen -R”
(当然,假设您使用bash作为外壳)
我认为您需要autossh。我已经使用了多年,并且与屏幕结合使用,使我的所有终端会话都完全可移植且透明。我只需关闭笔记本电脑,移至新位置,打开笔记本电脑,我的所有屏幕和嵌套屏幕都会自动连接。我什至不考虑了。
http://www.linux.com/archive/feature/134133
是基础知识...我用ruby建立了一个lil脚本,以针对给定的主机自动执行.screenrc中的过程。(我也进行ssh转发,所以在所有这些不同的地方,我都可以通过服务器建立连接隧道)
在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 / screen问题
最后,为了使我的ssh-agent保持运行,我使用了钥匙串,因为我有点像个shell头...我认为OSX可以提供一些东西来保持您的代理人...
这是我使用的方法:
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
我通常使用以下命令设置别名或shell函数:
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
}
您可能必须使正则表达式' screen-(r | DR) '适应您用于重新连接屏幕的确切命令。
我的方法的一个警告:如果计算机上运行另一个“ screen ”命令,则可能会出错。
sudo
。
我通常会在不同服务器上的工作场所中长期运行(超过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
由新Shell 使用,另一个由新Shell使用。不应有两个“启动”会话,但仍可以使用来启动第二个会话reattach -S new
;在这种情况下,代理将与~/.ssh/agent-screen
值共享。要恢复正常工作的转发代理,我将分离并重新登录。这样X${USER} = Xmyusername
可以确保不会sudo
在同一服务器上调用该代码。
我正在使用@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
这适用于我的屏幕会话中运行的所有应用。这将适用于您的屏幕会话中的所有新外壳。对于现有的Shell,您需要export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
在主机Shell上运行才能使其正常运行。
PS很抱歉将其添加为独立答案,而它只是基于@apinstein的答案。这样做是因为stackoverflow中的注释不支持代码块。
我尝试了让我们做屏幕和ssh-agent朋友建议的一种简单的衬纸,它对我有用。
首次登录到Target。只需执行一次。
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
这些都是非常好的答案,我的做法略有不同。启动新的ssh会话并重新连接屏幕后,我将SSH_AUTH_SOCK
根据root bash环境的内容重置环境变量。我只在使用svn时偶尔才需要ssh-agent访问,因此我只SSH_AUTH_SOCK
需要按照这些shell中的要求进行重置。
这使用proc文件系统,因此是Linux专用的。我仅在我只能访问的无头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"
上面的所有解决方案都面临竞争问题(在多个SCREEN会话中或在多个SSH连接中)。我能想到的唯一通用解决方案是,首先将SSH_AUTH_SOCK推入SCREEN服务器进程screen -r
,然后在每个交互式非内置命令之前将其拉入BASH会话中。不幸的是,SCREEN和BASH的设计没有意识到这类问题,因此很难正确实施(尽管向两个项目发布功能请求永远不会晚)。我试图克服BASH会话的这个问题,可以在这里找到:
安装:
$HOME/bin
,添加可执行位;确保在PATH $HOME/bin
之前执行以下操作/usr/bin
:
PATH = $ HOME / bin:$ PATH
将此添加到您的.bashrc
:
源$ HOME / bin / screen-helper设置
现在,您可以尝试在SSH会话中创建SCREEN会话,分离,断开连接,连接和重新连接,希望ssh-add -l
可以正确显示密钥。
ssh-agent
守护程序(如此处superuser.com/a/412052/376867所建议)不会遭受竞争状况的困扰,但会遭受过时的密钥环的困扰。而且更重要的是,将所有密钥与屏幕会话一起保留在远程主机上并不是很安全(如果提到上述问题,则更长的时间直到重新启动)。
我浏览了其他答案,找不到我的答案。这是我用的。创建一个~/.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
这样,您将使用两个屏幕会话-一个是“包装器”,一个是内部的。即使您注销,这也可以使后者保持活动状态,并使ssh-agent保持打开状态。另一个不错的功能是,它会记住您的窗口设置-如果您使用拆分窗口,则可能非常方便。
您可以在我的dotfiles的上下文中找到此功能。