为什么我在没有 root 的情况下会出现“屏幕正在终止”?

Lau*_*ent 25 permissions gnu-screen

我已经在 Fedora 19 上安装了 screen。当我以 root 身份通过 SSH 远程测试命令时,它运行良好。例如,如果我输入screen一个新的终端,模拟器就会启动并等待命令。我可以分离它等。但是,当我以标准用户身份通过​​ SSH 远程登录后尝试执行相同操作时,该命令会立即终止。我看到的唯一消息是[screen is terminating].

有人已经遇到过这个问题吗?是否与不良权限有关?

更新:

$ strace -e trace=file screen
execve("/usr/bin/screen", ["screen"], [/* 23 vars */]) = 0
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libtinfo.so.5", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libutempter.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libcrypt.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpam.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libfreebl3.so", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libaudit.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
access("/home/steam/.nethackrc", F_OK)  = -1 ENOENT (No such file or directory)
readlink("/proc/self/fd/0", "/dev/pts/0", 4095) = 10
stat("/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
lstat("/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
open("/var/run/utmp", O_RDONLY)         = 3
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
open("/etc/shadow", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied)
readlink("/proc/self/fd/0", "/dev/pts/0", 4095) = 10
stat("/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
stat("/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
lstat("/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
stat("/var/run/screen", {st_mode=S_IFDIR|0775, st_size=60, ...}) = 0
Directory '/var/run/screen' must have mode 777.
+++ exited with 1 +++
Run Code Online (Sandbox Code Playgroud)

我试图将权限更改为 777 但是当我执行时screen,我得到:

目录 '/var/run/screen' 必须具有模式 775。

因此,我已经恢复了我的更改。

小智 6

“必须具有模式 777”和“必须具有模式 775”之间的翻转是由 引起的strace

screen通常是一个 setuid 或 setgid 程序。它在执行时获得额外的权限,用于创建套接字文件和/或修改 utmp。

在跟踪进程时,setuid 和 setgid 被禁用。由低权限用户控制的跟踪进程可以接管被跟踪进程,因此它必须在没有额外权限的情况下运行,以避免给予原始用户过多的权力。

screen 检测它是否以 setuid 权限、setgid 权限或两者都不运行,并相应地调整其对目录权限的期望。

因此,这会产生一类无法轻松调试的问题strace

但是,如果您是 root,则有一个解决方法!如果跟踪进程以root身份运行,则被跟踪进程可以正常获得权限。所以这就是你要做的:

  1. 开通2个新航站楼
  2. 在第一个终端中,以root身份登录远程机器
  3. 在第二个终端中,以普通用户身份登录远程机器
  4. 用于ps在第二个终端获取普通用户的shell进程的PID
  5. 在第一个终端中,运行 strace -f -p SHELLPID
  6. 在第二个终端中,运行 screen 并观察它失败
  7. 在第一个终端中,您现在拥有用于找出真正错误所在的 strace 日志。

strace命令的关键添加是-f选项,它告诉它跟踪子进程。您需要它来跟踪将成为您指定的 shell 进程的子进程的屏幕-p

我也喜欢使用-ff和指定一个输出文件-o,如

strace -ff -o /tmp/screentrace -p SHELLPID
Run Code Online (Sandbox Code Playgroud)

这将为每个子进程创建一个单独的输出文件。之后,您使用它们阅读它们,less /tmp/screentrace*结果通常比使用单个-f.

更新

现在我已经看到了 strace 输出,我不知道到底出了什么问题,但这一行是跟踪中最令人惊讶的事情:

chown("/dev/pts/2", 1002, 5)            = -1 EPERM (Operation not permitted)
Run Code Online (Sandbox Code Playgroud)

几行之前,它创建了一个 pty,它被显示TIOCGPTN为 2。

open("/dev/ptmx", O_RDWR)               = 5
...
ioctl(5, TIOCGPTN, [2])                 = 0
stat("/dev/pts/2", {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 2), ...}) = 0
Run Code Online (Sandbox Code Playgroud)

但它无法吃掉它。我不知道为什么那个 chown 会失败,但是 chown 失败确实给出了 screen 放弃的合理原因。您可以通过添加-v到 strace 选项来获取更多信息,并查看stat后面的内容TIOCGPTN以查看谁拥有该/dev/pts/条目。


Cir*_*郝海东 5

确保没有其他人screen在使用该设备

这可以通过https://superuser.com/questions/97844/how-can-i-define-what-process-has-a-file-open-in-linux来实现:

sudo lsof /dev/ttyS0
Run Code Online (Sandbox Code Playgroud)

如果是这种情况,然后终止该进程。

由于某种原因,在这种情况下,sudo screen仍然可以访问该设备,但该连接将丢失字符,而这些字符将被其他screen.

发生这种情况的常见情况是,如果您使用 Ctrl + AD 分离screen,使其在后台运行,而不是使用 Ctrl + K 终止它。

确保用户对该文件有读写权限

例如,在 Ubuntu 上,您想要将用户添加到dialout组中: https: //askubuntu.com/a/133244/52975

sudo usermod -a -G dialout $USER
Run Code Online (Sandbox Code Playgroud)


小智 2

该错误的可能原因之一是不正确的 selinux 策略,但根据 redhat bugtracker 的说法,此类错误已在 fedora 17/18 中修复。

作为解决方法,您可以将变量更改SCREENDIR~/.bashrc类似$HOME/.screen.