Non-interactive & non-login shell environment?

Hello and thanks in advance for any help anyone can offer to straighten me out on this subject

I'm trying to understand non-interactive & non-login shells and having a hard time conceptualize the process a non-interactive & non-login shell goes through to start up. Particularly for background processes.

The way I understand things is when a process is started.... a region of memory is created and the child process replicates a duplicate environment of the parent by being forked. What's confusing me is when is the shell environment defined for a background process? When I think about how an interactive shell is started I get a little lost.

The way I understand an interactive shell is:

  1. User passes login ID to Linux kernel
  2. Linux kernel looks the user up in the /etc/password file and identifies the assigned shell
  3. the shell is started
  4. the shell reads the login scripts to define the shell environment for the user
  5. Linux produces a command prompt to indicate the shell is ready to accept commands

Do processes that start in the background have a similar process it steps through? This is how I envision it working:

  1. The process is forked by the parent process
  2. Linux identifies the user ID the process will runs as
  3. Linux looks the user id up in the /etc/passwd file
  4. the shell is started
  5. the BASH_ENV is read (If it was defined)
  6. the process interacts with the shell to pass commands to the API

For example... An Oracle database would have the user ID of oracle and be assigned the /bin/bash shell... Would this process accurately describe what it goes through when it starts?

For some reason this seems clunky and like I'm missing something... Could someone let me know if I'm on the right path please?

Thank you very much!

What you forgot to mention is how does a user connect... and so he has a TTY( or whaterver...) defined and keyboard, StdIn and StdOut are set to those...

what do you expect a non interactive shell to use as INPUT and output?

What will the non-interactive shell do when in the user env it reads TERM=VT100 or export DISPLAY=....
etc...

Thanks for the reply!

After giving things a bit of thought I'm mostly confused with background processes. In a hypothetical situation.... an Oracle database requires the user ID named oracle with the /bin/bash associated with it to run.

What I'm trying to figure out is when does a background process, like a database or web server, start the shell and read in any environment variables... and then does it use the shell to pass commands to the API.

If you could offer any insight to this I would be grateful!

Good practices will be to never use oracle for anything else than owner of the product, you create dba users owners of the instance it will run and put the user in group dba ( otherwise how will you recognise the processes of different running instances if they all belong to oracle? ... but thats not the point here... When are the environment set? well before you initialise the instance, that means usually you would have a start/stop script that will either set all the needed env variables or source from the user's .profile if the .profile ( or .bashrc etc... ) is written properly, that means testing if the shell is interactive or not ( yes I have boxes with more than 10 instances running... )

Thanks for the reply again... You sort of touched on the part of where I'm getting confused at. My understanding of a background process like a user ID for an Oracle database is it would be a non-interactive and non-login shell... From what I've read in the Bash man page a login script shouldn't run in a non-interactive shell

It specifies a script and not a process... Which makes me wonder how does a background process owned get the environment. Also, from what I've read a background process passes commands to the API... Which makes me confused as to where a shell comes into things in this sort of scenario

Once again... thanks for your replies and patience!

The "Linux" kernel handles the scheduling/multitasking and all the I/O, and it knows what an UIDs/owner is.
But it does not know what a shell is, and does not know that a UID is stored in a passwd file.
Nevertheless the kernel handle many atomic operations. Its API towards userland is in man page section 2; in Linux you can list them with:

man -k . | grep '(2)'

The userland is all the processes. The shell is a normal process. A lot userland code is stored in shared libraries, so the processes simply load the libraries and stay small. The ps -ef command also lists some kernel threads and assignes the PID 0, while the real processes in userland have PID 1 and higher.

The criteria interactive/non-interactive and login/non-login is a matter of the shell, or of the process that invokes it. You can read more of it in the man page

man sh
man bash

The invocation of a new process is done via a couple of the kernel API functions, basically fork() and exec() .

The shell is not actually in charge, it just helps arrange things. The shell isn't necessarily involved at all in creating the Oracle process, or creating any other process for that matter.

The one and only difference between "interactive" and "noninteractive" processes, as far as the kernel is concerned, is whether your process has a controlling terminal. The kernel knows what your terminal is even if your process doesn't - you can open it via /dev/tty. The kernel doesn't really care whether you have a terminal.

In the old days terminals were really terminals - physical devices attached to serial ports. /bin/login did the job of holding those ports open and reading username/passwords from them. Each port would have one /bin/login process running for it. These days, things like ssh have mostly taken over the job of sitting around and waiting for user input, terminals have become imaginary devices which get created and destroyed at need.

The login program creates your shell. It owns the terminal, and opens it, duplicating it onto file descriptors 0, 1, and 2 for you - standard input, standard output, and standard error. Then login runs your shell and lets it take over from there.

When a process is created, it receives a copy of the environment of its parent. So it comes down to where the parent got its environment.

OK, so, to understand the difference between background and foreground processes, and where system services get their environment, I must explain how almost everything works from the ground up... Wish me luck.

For starters, the "environment". Every process has a block of memory devoted to storing text variables. These are not shell variables: They are used by programs but not actually a part of them. Any process can get to these variables, shells, editors, anything. A large part of the shell's job is setting up these variables for everything else.

UNIX creates processes by cloning your own process then replacing it with something else. The environment is part of the memory which gets cloned. So to run nano, your shell calls fork to clone itself, then the clone calls exec to replace itself with a text editor. The environment isn't touched by this replacement -- nano still has a perfect copy of your shell's environment after it loads.

To clone a process, one must first have a process, so when a UNIX kernel starts, it runs the program init as the very first process. It has no controlling terminal (or gets rid of its controlling terminal shortly after starting - either way.) init will stay running for as long as your system does.

There's only a few things run by init: It will run a copy of getty on each physical terminal to provide "Username:" login prompts on them, and it will run "rc" to start system services. Unlike init, rc does not stay running, it just starts processes then quits.

rc runs shell scripts to start system services, traditionally found in /etc/rc.d/ or /etc/init.d/, called "init scripts". It loads /etc/profile first before loading an init script to start a system service.

So the point to my really longwinded answer is that the rc program (or whatever equivalent your system has) is responsible for running everything that's not a terminal login, and therefore controls their environments. Its own environment is probably next to nothing. If you really need a custom environment for a service, its the job of its init script to set it up. (though many UNIX and Linux distributions now have set up a better place for it in /etc/conf.d/ which is more or less a per-service /etc/profile kind of thing. rc is responsible for loading it.)

Now, foreground and background processes. These are meaningless terms without a terminal, because all "foreground" means is "in control of the terminal". When you run nano, your shell hands control of the terminal to it, and when nano quits, it gets that control back.