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

Mic*_*zek 16 ssh gnu-screen

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

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

$ screen -d -r foo
[2430.foo detached.]
Run Code Online (Sandbox Code Playgroud)

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

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


编辑:我的.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
Run Code Online (Sandbox Code Playgroud)

编辑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
Run Code Online (Sandbox Code Playgroud)

rus*_*ush 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.
Run Code Online (Sandbox Code Playgroud)

可能它会帮助某人,因为这是谷歌给我的断开连接后屏幕冻结的唯一页面。


小智 6

您的屏幕会话可能已挂起,等待您上次连接到屏幕的 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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,杀死进程 23214 将释放屏幕会话,您可以重新附加。

  • 如果没有父进程怎么办? (3认同)