I do not understand when does a shell, lets say bash, get executed, which program runs bash initially first.
-
What does the it in your question refer to? Are you asking what program starts the shell, or are you asking what (if any) program the shell (bash) starts first?– AnthonMar 6, 2014 at 9:27
-
@Anthon it refers to bash, means what program starts the shell(bash)– Parimal NMar 6, 2014 at 9:47
6 Answers
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 (systemd
or 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, login
will 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).
If you have pstree installed you can do:
pstree | less
and use /
to search for the program that you are interested in (bash
) you can then see what the parent and child processes for the particular tasks are (excerpt):
|-tmux-+-bash---python2.7---2*[{python2.7}]
| `-sh---x2vnc---x2vnc
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 bash
.
However, 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 "$@"
Replace the /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.
-
I don't see any danger in this - excepting, I guess, for the minute possibility that the single line per entry overloads
bash_runs.log
. It is curious that thedate
utility should be assumed readily available in$PATH
before even a log daemon starts. I also note that this is little likely to logsh
- which is most likely a built-in and so probably irrelevant, I guess - or any frominitramfs
. Certainly the Debian family will miss any calls todash
as well.– mikeservMar 12, 2014 at 4:39 -
You could mess up the script and become bashless :) You are right,
date
should be called by absolute path.– orionMar 12, 2014 at 9:11
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 init
.
So the answer to this question, I guess, is just as soon as you've configured it to be called.
MORE...
You can test this pretty easily - include your shell of choice in your initramfs image and add the parameter:
"init=/path/to/shell"
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
"init=/bin/sh"
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 /bin/sh
in 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
and 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 initramfs
, or 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.
-
The
init
in in theinitramfs
is not to be confused with the/sbin/init
that the system runs as pid 1. Theinitramfs
role is to mount the root file system and run/sbin/init
from there (which is generally not a script). The/init
command in the initramfs started by the kernel in that pre-boot phase is generally a script (so that's where the first shell is called, typically busybox sh), which after mounting the root filesystem pivots the root there and executes/sbin/init
(in the same process). Mar 6, 2014 at 10:11 -
@StephaneChazelas, while the
initramfs
'sinit
is running, it is PID 1. It laterexec(3)
s the "real" init. But that is beside the point, isn't it ;-)– vonbrandMar 6, 2014 at 13:00
Short answer: A shell runs when needed, and not earlier.
Longer answer:
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.