GNU屏幕死机,试图重新连接


16

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

99%的时间可以正常工作,但有时我会得到:

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

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

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


编辑:我的.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

发布您的〜/ .screenrc(如果定制的话,也许也可以发布/ etc / screenrc)可能会有所帮助
user2387

请发布输出strace screen -d -r foo(您可能需要制作screen可执行文件的未设置副本),并strace -p$(pidof SCREEN)在重新连接失败时进行发布。
吉尔斯(Gilles)'所以别再邪恶了'

@吉尔斯再次发生了;我添加了strace日志。strace主屏幕进程显示了write()通话中的类似内容
Michael Mrozek

当以前连接的屏幕没有完全断开连接时,似乎发生了这种情况(在这种情况下,我将其与另一台计算机相连,然后失去了网络连接)。可能screen试图写入不再存在的连接?
Michael Mrozek

主屏幕进程(称为SCREEN)仍然存在吗?它在做什么(strace)?
吉尔斯(Gillles)“所以-别再作恶了”

Answers:


8

不知道我是否和您有同样的问题,但是有时候,每次我的网络意外断开连接时,我的屏幕行为都会类似。

稍后(约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.

可能会有所帮助,因为这是Google断然拒绝我之后关于屏幕冻结的唯一页面。


我不完全了解如何基于该手册页条目,但这确实为我解决了问题。我设置nonblock 5了一阵子,然后又碰到了这个问题,五秒钟后,它突然正常附着了
Michael Mrozek

6

屏幕会话可能已挂起,以等待上次连接到屏幕的外壳程序的伪终端。有时,丢失的连接会留下该外壳,并且屏幕必须超时才能脱离。

如果运行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
如果没有父进程,该怎么办?
d33tah 2015年

今天,这对我有所帮助,杀死了sshd使得屏幕再次响应!节省了数小时的工作!
user230910

4

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

我不记得确切的细节,但我确实记得大约一个月或三个月前,系统上有一个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


在发布Debian 7 Wheezy之前,此问题已得到解决。尽管它存在于相应的上游发行版或git快照中。参见bugs.debian.org/683228
Axel Beckert

今天,这只是在较旧的Centos 6安装上发生在我身上。谢谢!
Mike Andrews

我只是在Gentoo上被这个咬住了,我从4.3升级到4.4。
jlh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.