0

is it possible to kill/exit the current bash shell and start a new one with some command? Something like

kill -9 $PPID && bash -c echo 'I started new!'

which does not work obviously.

4
  • 6
    (1) XY? What is the purpose? (2) Do you know the exec builtin? Commented Mar 18 at 9:50
  • 1
    Hi Juergen, nice to have you around, but: any starting of any other executable always replaces the process it was done on (on UNIXoid operating systems). Your shell "survives" this by forking first. And exec does the running without the forking, so that already works. Feels like a pretty fundamental concept! As Kamil asks, hm, you're asking interesting questions, but it seems you've forgot to give us the "bigger picture", of what you want to achieve that way (hint: most of your environment might simply "survive" that replacement, so whatever you are trying to clean up that way might, too.) Commented Mar 18 at 11:45
  • 2
    Strictly speaking, no since you kill the process that was supposed to launch the new bash shell and dead processes cannot launch things. However, if you explain what you are really trying to do and why you want this, we might be able to find a workaround. Would you be willing to start a new shell first and then kill the old one, for example?
    – terdon
    Commented Mar 18 at 11:45
  • @MarcusMüller: Thx for kind words. I will rethink all of this...
    – Juergen
    Commented Mar 18 at 12:20

2 Answers 2

1

You don't kill shells, you kill processes. You can start both processes and commands including shells though.

Starting a process is done by cloning (forking) one.

Starting a command would mean executing it.

Something typically starts a shell (let's say bash) script by forking itself, and in one of the branches of the fork (typically the child) running execve("/path/to/bash", ["bash", "/path/to/the-script"], environ).

That process will read the contents of the-script one line at a time and interpret the shell code in it.

Before doing that, it will initialise a few special parameters including $$ for the pid of the process that executed it, $PPID for the parent of that process (at that time; that may be the other branch of the fork mentioned above, or that could be pid 1 or that of the child subreaper).

Some of the code it reads will often cause the shell process to spawn more processes (fork itself) in some of which it will execute more commands. After all, a shell is a language interpreter specialised in running commands, and those have to be run in separate processes if you want to be able to run more than one.

For those commands that are shell builtins such as kill, the shell doesn't need to fork itself to execute them, though.

It is worth noting that in those child processes, $$ and $PPID remain unchanged, regardless of whether the corresponding processes are still alive or not. They are not the pid and ppid of the shell process that happens to be expanding those parameters, they are the pid and ppid of the process that originally executed the shell interpreter.

So when you do kill -9 $PPID, that will (as long as $IFS has not been modified as you forgot to quote that expansion) run the kill command in the same process, which may or may not be one that originally executed the shell if that code is found as part of a subshell or a pipeline for instance, and send the SIGKILL signal (a signal that cannot be handled and should only be used as a last resort) to whatever the parent process of the one that executed the shell at the time it initialised itself.

That will not kill the shell, though the shell might die as some consequence of its parent dying. For instance, if the parent is a terminal emulator, the shell process(es) might receive a SIGHUP as the terminal hung up.

If you replace it with kill "$$", then the process that initially executed the shell in a child of itself and might still be around waiting for that child process, will see it having died and carry on with its own business.

If it's the process with $$ as pid that ran that kill "$$", then it will die and won't be able to carry on with bash -c echo 'I started new!'.

What you can do here though is:

exec bash -c echo 'I started new!'

exec should rather have been called no-fork. That tells the current shell process to execute bash in the same process, not in a child one, so basically that will restart the shell, re-execute it in the same process. That process does not terminate. If it still has a parent waiting for it, that parent will not see its end until that new bash shell calls exit or gets itself killed.

You could also do:

bash -c echo 'I started new!' & exit

In which case the current shell process runs bash in a child of itself, but does not wait for its termination and exits straight away.

Then, if it has a parent, that parent will see that shell process terminating but will not be aware of the new bash process (its grandchild).

0

Sure. As soon as you login to your system, type "bash" to open a new shell on top of your login shell.

Then do whatever you wish to do in that shell environment.

When you're ready to kill that and start "clean" in a new shell, just type "exit", then "bash" again.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.