我已将 shell 配置为exec screen
启动时,除非它已经在屏幕会话中运行。因此,在 TTY 中,进程树将如下所示:
login───screen───screen───zsh.
几乎在每种情况下,这都是我想要的,但有时我想在没有屏幕的情况下运行某些东西,并且我想在不改变我的通常设置的情况下这样做。我正在寻找一个用其他东西(例如 shell)替换最顶层屏幕进程的命令,如下所示:
login───bash,
无需重新注销并对 my.zshrc
或 use进行临时更改chsh
。
答案1
你应该开始屏幕会话,无需.zshrc
,exec
只需screen
。exec
用新进程替换当前进程。因此,您将永远不会回到原始流程,因为它不再存在。
如果开始时没有exec
,pstree
那么看起来与此类似(我添加-p
到 pstree 以显示 PID 以供理解):
|-login(857)---zsh(31597)---screen(1105)---screen(1108)---zsh(1109)-+-pstree(1209)
$ echo $$
1109
我们现在处于 的子进程中screen
,因此在screen
.当您现在想要在screen
close之外执行某些操作或使用-screen
分离它时。再次:ctrla dpstree
|-screen(1108)---zsh(1109)
|-login(857)---zsh(31597)-+-pstree(1481)
$ echo $$
31597
第一行是screen
与内部运行的外壳分离的,第二行是当前正在运行的外壳(我们现在所在的位置)。如您所见,该$$
变量包含第一个进程的 PID zsh
。
要返回屏幕,只需调用:
screen -r
现在看起来与第一个场景类似:
|-screen(1108)---zsh(1109)-+-pstree(2118)
|-login(857)---zsh(31597)---screen(2112)
$ echo $$
1109
注意 PID:我回到了 (1108) 的子 shell screen
。该screen
进程(1108)不再是原始屏幕(1105)的子进程,因为该进程不再存在。这就是 1108 被重新设置父级的原因(他的父级现在的init
PID 为 1)。当我调用screen -r
重新连接时,使用新的 PID (2112) 创建了一个新的屏幕进程。这些screen
进程通过简单的 unix 套接字或通过命名管道相互通信。
答案2
我的建议是,不要用屏幕替换外壳,而只需根据屏幕是否正在运行来启动或连接,然后您就可以自由地使用ctrl+ a-d
if [[ ! $(screen -ls 2>&1) =~ .*No.Sockets.* ]] ; then
screen -U -x
else
echo 'No existing screen sockets found, launching screen!'; screen -U -S session -s `which zsh`
fi
应该在 ~/.bash_profile 或 ~/.bashrc 中粘贴 ↑,然后将用户的默认 shell 设置为 bash。每次您创建新的屏幕窗口时,这都会分叉新的 zsh 进程,并始终将您重新连接到屏幕会话,或者启动一个新的屏幕会话(如果它未运行)。这样你就可以脱离屏幕并在屏幕之外运行东西。例如,如果您想移动屏幕上已经存在的进程之一,您可以使用类似的方法来实现雷普特尔。
答案3
下面的方法可能有点棘手,但可以解决您的问题。
您可以通过编辑 /etc/passwd 文件并复制用户的行来创建用户的副本。仅更改用户名(第一个字段)。通过 为您的“新”用户设置密码passwd newuser
。最后更改您的.zshrc
并将其替换exec screen
为对用户名的检查:
if [ "`id -un`" != "newuser" ]
then
exec screen
fi
当您想在没有会话的情况下进行会话时,exec screen
可以使用备用用户登录,该用户实际上与常规用户相同。
也许对于您想要实现的目标有更好的选择,但这可能会帮助您......