Can a process run regardless of any shell?
Solution 1:
Sanity check: As far as I understand, the shell is the interface through which the user can interact with the OS, i.e.: run other processes.
Yes, but a "shell" is specifically a user interface, not a programming interface. Other programs are not required to interact with it – they can directly use the same system calls to create new processes.
So the command-line shell is on the same level as other programs, e.g. service managers, or graphical user interfaces (graphical shells).
Although the shell (e.g. Bash) is just another process.
Yes. On Unix-like systems it is a completely normal, unprivileged process.
Is there a way to run a process that will not be a child of a shell process?
From a user's perspective: yes, there are several ways.
-
Most shells have an
exec
keyword which causes the new program to replace the shell (retaining the same PID and parentship), which is probably not what you meant, but technically what you asked for. -
Graphical desktop sessions will often start without invoking bash or any other shell, and this automatically applies to apps launched through the graphical menus. The app's parent will be whatever process was responsible for showing the menu (e.g. the window manager or the panel).
-
The currently popular systemd init system does not use a shell at all when starting services, so you can define a .service and start it – the service's parent will be init itself. It also has a feature allowing temporary services to be created on-the-fly using
systemd-run
, with the same results.
From a programmer's perspective, just use the fork()
and execve()
system calls to launch a new process. (There are OS-specific details, e.g. fork() might in fact be a wrapper for a different call, but it still works the same way.)
Indeed, even if the program wanted to invoke a shell, it would do so by creating a new child process and running /bin/sh using the same fork+exec. There is no special system call to run a shell. (The programmer could use e.g. system() when writing in C, or os.system() in Python, but those are still just convenience wrappers around fork/exec.)
Environment variables: In bash, there are several scripts that run when you spawn a shell, e.g. .bashrc, .bash_profile, etc. (depends on the type of shell - interactive vs non-interactive, login vs non-login). These scripts define the environment variables. If there's a way to run a process regardless to any shell, where do environment variables come from?
Well, sometimes they don't. (It's a real practical problem when trying to make graphical apps pick up environment customizations, depending on how that particular graphical environment starts.)
Overall, though, environment variables are not unique to CLI shells. Each process, no matter how it was started (including even the init process), receives an array of strings containing its command line – and an array of strings containing its environment variables. When launching a child process, it can either specify a different environment or allow a copy of its own environment to be inherited.
So when you log in, your shell already receives a few initial environment variables from its parent. Those startup scripts (bashrc, etc.) are just a convenient place for a user to customize the environment variables that the shell's child processes will then inherit.
Many parts of this answer also fully apply to Windows – although its graphical interface is a bit more complex, the CLI shells (cmd.exe and PowerShell) are still ordinary programs that aren't used at all in normal operation. The only major difference is that Windows has a single "CreateProcess" call instead of the Unix-style separate "fork + exec" calls.
Solution 2:
-
That is correct. Ultimately, the shell will perform the
exec
system call, which is available in all POSIX-compliant operating systems, and more generally in all Unix-like operating system, including Linux. Other operating systems have similar concepts. On Linux, theexec
system call will ultimately call theexecve
function, which is provided by the kernel and does the actual job of loading the executable file and running it. -
Yes. Any process can call
exec
, and need not be a "shell". For example when you launch a program by clicking in a filesystem browser, the desktop software is the one performing theexec
call, there is no shell. Note that the process becomes the child of the desktop software that launched it. All processes are the children of one other process, except the very first one, which is calledinit
and has PID 1. It is responsible for setting up the operating system at start and launching all other processes, such as background services and desktop login. On Linux nowadays,systemd
is often used as theinit
process, but there are other alternatives. -
There are several variants of
exec
(execl
,execle
, ...) that have various arguments in addition to the name of the program to be run. Ultimately, theexecve
system call takes a program name, a list of strings which are the command-line arguments, and a list of strings which are the environment variables. For example when launching software from a filesystem browser, the environment variables may be copied from the ones of the filesystem browser itself, possibly modified by the filesystem browser. This is entirely up to the programmers of the filesystem browser.
Some further reading:
- https://en.wikipedia.org/wiki/Exec_(system_call)
- https://en.wikipedia.org/wiki/Fork%E2%80%93exec
- https://man7.org/linux/man-pages/man2/execve.2.html