3

I have configured my shell to exec screen when it starts, unless it's already running within a screen session. So in a TTY, the process tree will look like something like this:

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

In almost every case, this is what I want, but sometimes I would like to run something without screen, and I would like to do so without changing my usual setup. I'm looking for a command that replaces the topmost screen process with somehting else, e.g., a shell, like this:

login───bash,

without having to log back out and make temporary changes to my .zshrc or use chsh.

1

You sould start the screen session in you .zshrc without exec, just screen. exec replaces the current process with the new one. So, you will never get back to the original process because it doesn't exist anymore.

If started without exec, pstree would then look similar to this (I added -p to pstree to show the PIDs for comprehension):

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

We are now in the child process of the screen, hence inside the screen. When you now want to execute something outside of the screen close the screen or detach for it with ctrl-a d. Again pstree:

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

The first line is the detachted screen with a shell running inside, the second one the currently running shell (Where we are now). As you see the $$ variable contains the PID of the first zsh process.

To go back into the screen, simply call:

screen -r

It looks now similar as in the first scenario:

|-screen(1108)---zsh(1109)-+-pstree(2118)
|-login(857)---zsh(31597)---screen(2112)
$ echo $$
1109

Notice the PID: I'm back in the shell that is a child of screen (1108). That screen process (1108) is not anymore a child process of the original screen (1105), because that process doesn't exist anymore. That's why 1108 got reparented (his parent is now init with PID 1). At the point where I called screen -r to reattach back, a new screen process was created with a new PID (2112). Those screen process talk over simple unix sockets or via named pipes with each other.

1

What I would recommend rather than replacing the shell with screen just having it launch or attach based off of whether or not a screen is running then you have the freedom to detatch with 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

Should stick ↑ in either ~/.bash_profile or ~/.bashrc then set your user's default shell to bash. This will fork new zsh processes everytime you create new screen windows and always reattach you to your screen session or start a new one if it isn't running. That way you could detatch from screen and run things outside of it. And if for instance you wanted to move one of the processes that was already in the screen you could do so with something like reptyr.

0

The following method is maybe a bit tricky but can be a solution to your question.

You might create a duplicate of the user by editing the /etc/passwd file and duplicate the line of your user. Only change the username (first field). Set a password for your 'new' user by passwd newuser. Finally change your .zshrc and replace the exec screen with a check on the username:

if [ "`id -un`" != "newuser" ]
then
    exec screen
fi

When you want to have a session without exec screen you can login with the alternate user which is actually the same as your regular user.

Perhaps there are better alternatives for what you are trying to achieve but this might help you...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.