标题: 普通用户无法进入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.
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
理论指导实践,创建普通用户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排查。