GNU 屏幕在尝试重新连接时冻结

GNU 屏幕在尝试重新连接时冻结

我有几个长时间运行的 GNU 屏幕会话。我通过 ssh 连接到它们正在运行的盒子,screen -d -r foo如果它们连接到其他任何地方,则运行以分离它们,然后将它们附加到我当前的窗口中。

99% 的情况下这都可以正常工作,但有时我会得到这样的信息:

$ screen -d -r foo
[2430.foo detached.]

……什么也没有发生;我根本无法回到shell。在另一个窗口中尝试做同样的事情,我唯一能做的就是销毁该屏幕会话(丢失其中运行的所有程序)并重新创建它

为什么会出现这种情况?发生这种情况时如何避免或重新成功连接?


编辑: 我的.screenrc

startup_message off
defwritelock off
bind q quit
caption always '%{gk}   (%n) %t                   %{y}%d %M %Y :: %c:%s                   %{b}%W%{d}'
screen -t ZSH
autodetach on
shelltitle ZSH
defutf8 on

编辑strace:尝试附加时日志的结尾:

readlink("/proc/self/fd/0", "/dev/pts/14", 4095) = 11
stat64("/dev/pts/14", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 14), ...}) = 0
stat64("/dev/pts/14", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 14), ...}) = 0
geteuid32()                             = 1000
getegid32()                             = 1000
open("/dev/pts/14", O_RDWR|O_NONBLOCK)  = 3
geteuid32()                             = 1000
getegid32()                             = 1000
close(3)                                = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
umask(0)                                = 022
lstat64("/var/run/screen", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
access("/var/run/screen/S-mrozekma", F_OK) = 0
stat64("/var/run/screen/S-mrozekma", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
umask(022)                              = 0
uname({sys="Linux", node="etudes-2", ...}) = 0
rt_sigaction(SIGHUP, {0x806e520, [], 0}, {SIG_DFL, [], 0}, 8) = 0
geteuid32()                             = 1000
getegid32()                             = 1000
open("/var/run/screen/S-mrozekma", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
getdents(3, /* 6 entries */, 32768)     = 124
stat64("/var/run/screen/S-mrozekma/2386.chat", {st_mode=S_IFIFO|0700, st_size=0, ...}) = 0
geteuid32()                             = 1000
getegid32()                             = 1000
open("/var/run/screen/S-mrozekma/2386.chat", O_WRONLY|O_NONBLOCK) = 4
geteuid32()                             = 1000
getegid32()                             = 1000
fcntl64(4, F_SETFL, O_RDONLY)           = 0
geteuid32()                             = 1000
getegid32()                             = 1000
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
geteuid32()                             = 1000
getegid32()                             = 1000
setuid32(1000)                          = 0
setgid32(1000)                          = 0
stat64("/var/run/screen/S-mrozekma/2386.chat", {st_mode=S_IFIFO|0700, st_size=0, ...}) = 0
getpid()                                = 30081
write(4, "\0gsm\4\0\0\0/dev/pts/14\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 12336

答案1

不确定我是否遇到与您相同的问题,但有时每次网络意外断开时我都会出现类似的屏幕行为。

一段时间(大约 10-15 分钟)后,屏幕再次可用,可以重新连接。经过一番调查,我在手册页中发现了一个小注释:

   nonblock [on|off|numsecs]

   Tell  screen  how to deal with user interfaces (displays) that cease to
   accept output. This can happen if a user presses ^S or a TCP/modem con‐
   nection gets cut but no hangup is received. If nonblock is off (this is
   the default) screen waits until the display restarts to accept the out‐
   put.  If  nonblock is on, screen waits until the timeout is reached (on
   is treated as 1s). If the display  still  doesn't  receive  characters,
   screen will consider it "blocked" and stop sending characters to it. If
   at some time it restarts to accept characters, screen will unblock  the
   display and redisplay the updated window contents.

也许它会对某人有所帮助,因为这是谷歌给我的关于断开连接后屏幕冻结的唯一页面。

答案2

您的屏幕会话可能挂起,等待您上次附加到屏幕的 shell 的伪终端。有时,丢失的连接会导致外壳离开,并且屏幕必须超时才能与其分离。

如果运行ls -l /proc/<screen_pid>/fd/<descriptor_of_hung_write>,您应该看到它是上一个 shell 会话的 pts 。

一旦您终止了附加的 bash/shell 会话,您将能够重新附加。

# ps auwxf|grep -B2 screen
root     23214  0.0  0.0 109304  4016 ?        Ssl  19:13   0:00  \_ sshd: root@pts/6 
root     23566  0.0  0.0 117400  2272 pts/6    Ss   19:13   0:00      \_ -bash
root     10445  0.0  0.0 125156  1156 pts/6    S+   19:23   0:00          \_ screen -ADR MYSCREEN

在这种情况下,终止进程 23214 将释放屏幕会话,您可以重新连接。

答案3

自这些屏幕会话启动以来,屏幕是否已升级?

我不记得了精确的细节,但我确实记得大约一三个月前,apt-get dist-upgrade我的系统上有一个(到 debian sid)升级屏幕,并且 postinst 警告我有关不兼容的升级。已保留旧屏幕的副本(位于 /tmp IIRC 下的某个位置)以能够重新附加到旧会话,但建议终止并重新启动它们。

您报告的症状听起来与我不小心尝试使用新的 /usr/bin/screen 重新连接到旧屏幕会话时所看到的类似。

六月份的 dpkg.log 可能是这样的:

2012-06-14 08:11:51 upgrade screen:amd64 4.0.3-14 4.1.0~20120320gitdb59704-2

相关内容