标题: 普通用户无法进入screen状态的排查 创建: 2022-04-11 16:32 更新: 2022-04-12 15:23 链接: https://scz.617.cn/unix/202204111632.txt -------------------------------------------------------------------------- 目录: ☆ 现象描述 ☆ 排查结论 ☆ 排查过程 ☆ 其他讨论 1) 如何判断处于screen中 2) 用tmux替代screen 3) ChatGPT/New Bing -------------------------------------------------------------------------- ☆ 现象描述 本文说的screen是"screen manager with VT100/ANSI terminal emulation"。完全 没听过、没用过这玩意儿的,不必往下看。 在Ubuntu 22安装过程中创建的普通用户user1可以用screen;后来自己创建的user2 不能用screen,也不报错,就是不进入screen状态;root可以screen。 ☆ 排查结论 user2的实际名字是none,这是screen的保留关键字,在程序内有检查,有其他用途。 普通用户名为none时,会触发意料之外的流程,导致none用户无法进入screen状态。 这事儿可气在none执行screen时,静默结束,无任何报错。 只关心结论者到此止步。 ☆ 排查过程 起初以为是权限问题,毕竟root可用,毕竟初创普通用户隶属多个特权组。将user2 加入特权组,情况依旧。放狗、问GPT,都说是权限问题,GPT捏造出名为screen的特 权组,建议将user2置入该组。再就是说动用setuid技术,给screen加s位。未测试s 位,从排查结论看,本例即使用了s位,也解决不了。即使s位能解决,也不想用,我 想知道为什么user1能用、user2不能用。 检查了几处权限设置,无异常 ls -l $(which screen) ls -l $(tty) ls -l /var/run/utmp ls -l /var/run/screen/ ls -ld /var/run/screen/S-$USER 试图常规查看日志,无果 screen -L -Logfile /tmp/screenlog 接下来用strace观察user1、user2执行screen的过程 strace -v -ff -o /tmp/screen screen 这是我的常用strace参数组合,"-ff"是"--follow-forks --output-separately"的 缩写格式。user1成功,生成一批screen.;user2失败,只有2个screen.。 用BC比较它们,父进程无本质差异;第一个子进程有本质差异,user2在此有一行 write(1, "Could not create user info\r\n", 28) = 28 此行只在strace时看到,stdout并无输出。拖源码回来看看 cd ~/src/ mkdir screen cd screen/ apt-get source screen tar cfj screen-4.9.0.tar.bz2 screen-4.9.0 回Windows中展开tar.bz2,7-Zip展开失败,说没有权限创建"symbolic link";在 WSL1中"tar xfj"展开成功。用Source Insight查看screen源码,搜前述错误信息, 定位至 -------------------------------------------------------------------------- /* * screen-4.9.0\screen.c */ freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); freopen("/dev/null", "w", stderr); /* * This guarantees that the session owner is listed, even when we * start detached. From now on we should not refer to 'LoginName' * any more, use users->u_name instead. */ if ( UserAdd( LoginName, (char *)0, (struct acluser **)0 ) < 0 ) { Panic( 0, "Could not create user info" ); } -------------------------------------------------------------------------- stdout、stderr全部重定向到/dev/null,伪终端看不到Panic()的错误提示,小坑。 -------------------------------------------------------------------------- /* * screen-4.9.0\acls.c * * Add a new user. His password may be NULL or "" if none. His name must not * be "none", as this represents the NULL-pointer when dealing with groups. * He has default rights, determined by umask. */ int UserAdd ( name, pass, up ) { if ( !up ) { up = FindUserPtr( name ); } if ( *up ) { .. /* * he is already there */ return 1; } /* * "none" is a reserved word */ if ( strcmp( "none", name ) ) { *up = (struct acluser *)calloc( 1, sizeof(struct acluser) ); } if ( !*up ) { /* * he still does not exist */ return -1; } -------------------------------------------------------------------------- UserAdd("none")必然失败,其内部要求用户名不得是"none"这个保留关键字,至此 算是破案。 事后诸葛亮,既然none是screen的保留关键字,man手册应该有提,细看,果然。 -------------------------------------------------------------------------- aclgrp username [groupname] A user is removed from all groups the special value none is used for groupname. -------------------------------------------------------------------------- 即是说,"aclgrp someuser none",相当于"aclgrp someuser "。但man 中并未明确警告勿用none做用户名。 理论指导实践,创建普通用户user3,避开none这个名字,user3可用screen,闭环。 ☆ 其他讨论 1) 如何判断处于screen中 有许多办法,此处只列其中比较简单易行的判断办法 位于screen中 $ pstree -s $$ systemd───sshd───sshd───sshd───bash───screen───screen───bash───pstree $ echo $TERM screen $ echo $STY 6957.pts-1.Ubuntu-22 "Ctrl-A T"显示时间,具体操作是,按完Ctrl-A,保持Ctrl,松开A,再按T。 退出screen后 $ pstree -s $$ systemd───sshd───sshd───sshd───bash───pstree $ echo $TERM vt100 $ echo $STY (空) 2) 用tmux替代screen none是screen的保留关键字,tmux对此无特别要求,none可以用tmux。 参看 《远程SHELL中进程因TCP连接中断而失去控制的预防及救急方案》 https://scz.617.cn/unix/201902151750.txt 3) ChatGPT/New Bing GPT应该把本篇的信息收录进去,下次再有人问类似问题,除了权限问题,提醒检查 用户名,提醒使用strace排查。