从屏幕内替换屏幕进程

从屏幕内替换屏幕进程

我已将 shell 配置为exec screen启动时,除非它已经在屏幕会话中运行。因此,在 TTY 中,进程树将如下所示:

login───screen───screen───zsh.

几乎在每种情况下,这都是我想要的,但有时我想在没有屏幕的情况下运行某些东西,并且我想在不改变我的通常设置的情况下这样做。我正在寻找一个用其他东西(例如 shell)替换最顶层屏幕进程的命令,如下所示:

login───bash,

无需重新注销并对 my.zshrc或 use进行临时更改chsh

答案1

你应该开始屏幕会话,无需.zshrcexec只需screenexec用新进程替换当前进程。因此,您将永远不会回到原始流程,因为它不再存在。

如果开始时没有exec,pstree那么看起来与此类似(我添加-p到 pstree 以显示 PID 以供理解):

|-login(857)---zsh(31597)---screen(1105)---screen(1108)---zsh(1109)-+-pstree(1209)
$ echo $$
1109

我们现在处于 的子进程中screen,因此在screen.当您现在想要在screenclose之外执行某些操作或使用-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 被重新设置父级的原因(他的父级现在的initPID 为 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可以使用备用用户登录,该用户实际上与常规用户相同。

也许对于您想要实现的目标有更好的选择,但这可能会帮助您......

相关内容