I do not understand when does a shell, lets say bash, get executed, which program runs bash initially first.
The boot sequence of linux/unix has many stages, and there are many references and answers on this site that explain the detail. But to summarise;
Eventually the kernel is loaded with drivers so that the disk and devices can be used, it then starts process with a
pid (process id) of 1.
Traditionally this program was a program called
init but today there are several newer programs (
upstart). It depends on your distribution and version, which one is used.
Starting up is a tiered process.
There is a concept of escalating run levels (1,2,3,4,5,6 ...) and the start up program will flip between these levels automatically or staged (so that the user can gain control).
- being the initial step (single user mode),
- multi user mode,
- multi user with networking
- GUI mode ...
- .. 6., ...
These run levels are not fixed in stone either, they depend on the distribution and start up program being used (init, systemd, ...) and convention.
The levels also depend on how the staged start-up/shutdown pattern has been designed. (think, linux is used in routers, android phones, servers and desktops all with different requirements).
In order to transgress from one run-level to another various other programs (services), like bind (for DNS), networking, routing, webservers, ... are started or stopped, and
bash may be used then to run a particular script which starts or stops a service.
Eventually you need to login, either at a console or at a graphical interface, and you may be prompt for your username and password.
Let's take a simple route, and say you are at a non-graphical console, and the
login program is prompting you to authenticate. When you pass, it will read which shell is configured for the entered username from
/etc/passwd and start it, with input and output set to your console and then you have the prompt and can start doing your work. So in this scenario,
init starts -> login which starts -> bash
So every process is a child of the first process, (it might be more accurate to say, every process has pid 1 as an ancestor). In the above example,
exec the shell, replacing login process with bash, the process id doesn't change. When you look with
ps it looks like bash was started by init because it's parent pid is 1, but there was a chain of events.
There's nothing really stopping
pid 1 from just starting bash at the console (if pid 1 can work out what the console is at that point) and this is down to how the start-up sequence is designed. (I had to do that once, but it is not normal practice).
In Unix, the shell is just another program. There are even a plethora of shells around, catering to different users' particular perversions in the command line interface area. POSIX mandates that a particular shell (essentially a stripped down Bourne shell) must be available.
The Unix shells are much more than just command interpreters, however. They interpret quite capable programming languages. It is common to write a script of shell commands to automate repetitive tasks. This is obviously slow, but as long as this is just used as glue to string together other commands for infrequent tasks, this doesn't matter. Flexibility might be much more important, in that the script can be edited on the fly.
As other answers explain, starting up a system is complex, parts of which can benefit from scripting some tasks. As the shell is guaranteed to be available, it is a natural choice for this. Tasks run periodically (by cron or similar) are normally written as shell scripts too.
Once the system offers a user to log in, after checking credentials a program is launched to interact with them. That this by default is the same shell mentioned above is incidental, one can certainly select another program. There are lots of alternative shells, and other programs might make sense in special circumstances.
The shell is executed during boot only if shell scripts are called. The traditional
init system is built around shell scripts (every service/daemon is started from a shell script). Most services are started when the system goes into multiuser mode. Some things may get started before (mounting the filesystem may involve calling scripts).
On linux, the initsrcipts are run by
sh, which is normally a link to
systemd, which is starting to replace
init on many distros (even debian is talking of switching).
systemd is designed to not use initscripts at all and instead starts the daemons and mounts by itself, together with keeping control over them and restart them if they fail. It is entirely possible that a
systemd boots without running shell interpreters, although you can always have a service that is a shell script by itself.
Of course, user's default shell is started at login, but that's after the boot process. If you boot into a display manager (most user-centric distros do this by default), the shell may never be run at all. They even hude the terminal emulator so that one must dig through levels of menus to get to it.
With a little hack, you can log all bash instances that start. Beware, it is dangerous, you may break the system. Temporarily copy your bash from
/bin/ to somewhere else (
/usr/local/bin is a good place, because it comes later in $PATH). Write a shell script like this:
#!/usr/local/bin/bash (/bin/date && echo "$$:$@") >> /root/bash_runs.log exec /usr/local/bin/bash "$@"
/bin/bash with this script. It internally calls the real bash, so this is not an endless loop. It logs the date and PID of the process (don't use logger, the logging system may have started yet). You will also see what scripts are run.
I repeat: don't do this unless you fully understand all steps. And don't forget to rollback all the changes after you are done.
The kernel's first and primary goal upon load is to find and call
init - userspace. Your
initramfs is unlikely to be anything more than a Linux disk image containing that 'init' and as few files as were needed to pack into that image for
init to find and mount your actual root filesystem. These are not hard and fast rules, per se, but they are the defacto standard.
The real problem with answering this question is that though
init very often is a shell and the few files that accompany it in initramfs are just shell scripts and a few kernel modules required to mount your root device, it certainly doesn't have to be. The kernel doesn't care - it just wants
So the answer to this question, I guess, is just as soon as you've configured it to be called.
You can test this pretty easily - include your shell of choice in your initramfs image and add the parameter:
to your bootloader's kernel commandline. So long as your shell's dependencies are met your next boot should provide you an interactive prompt in early userspace.
Probably not even adding your shell is necessary, though, as there's a pretty strong possibility that your init already is a scripted
busybox session and
will do just as well - though I expect the "just as well" part is debatable. In any case, if you've ever found yourself at one of those "emergency recovery prompts" it was probably just
initramfs, unless you use
grub and your kernel failed to load entirely, in which case it definitely wasn't.
Stephane comments below on the difference between
init. It is certainly true that once
switchroot is called the next program invoked is a lot less likely to be a shell than it was when the kernel unpacked
initramfs (which happens whether you provide one or not, by the way) and called
init. And definitely the post on which he commented had a lot less to say on the matter than does this edit, but at that point any
init called is second string - it's just userspace calling userspace.
This is significant in that any control surrendered is given voluntarily, usually in a shell script, and is not a necessity for operation as was the handoff from kernelspace to userspace. This can manifest in different ways - like your option never to call
switchroot at all and run the os out of
systemd having to kill
udev in early userspace so it can start a new
udev process as its child - but I hope I now make a little less muddy the truth that
init is only ever called once and any program named
init called later is only carrying the
init torch after the initial process passes it on.
Another answer here comments that
init is traditional but is likely to be something else today. I'm not certain I follow, but to the best of my knowledge
init was before and still remains the initial userspace process called by the kernel upon load, as is evinced by the
init= kernel parameter mentioned above, and, more often than not,
init is a shell.
To sum up, it is probably best not to think of
init as the name of a program at all, but instead as the name of the
parameter which specifies an executable program to which the kernel surrenders initial control of userspace as a whole.
Short answer: A shell runs when needed, and not earlier.
The most obvious time the shell runs is when a user logs on. The tty program handling the user's session will start the shell.
Other possibility, is when it's needed by a cronjob, if the cronjob is using a script instead of a binary.
And there's also the possibility that to start some services, the shell needs to be invoked to run a script.