Interactive, non-interactive, login, non-login shell

shell

This blog explains interactive, non-interactive, login and non-login shell

Overview

Shell, especially bash shell, is widely used in our daily work. We usually use some SSH terminal tools like putty to connect to a remote Linux server, and then interact with it using a shell. We type commands via keyboard and then get feedbacks from the terminal console. We also often write shell scripts to automate some set of tasks. These scripts may run at background continuously or may run directly in the terminal console and we get very straightforward feedback about what happens. Sometimes we also use commands or write scripts in a way that the commands or scripts will execute commands on some other servers but not in the local where the scripts is located. This happens frequently when you have a cluster of Linux hosts need to be managed but you're willing to put management scripts in only one of them.

All activities more or less are related to concept of shell instance types from technical point of view. Sometimes we get problems (one example later) due to lack a clear picture for these concepts. In this post, I will give a overall idea about the concepts of shell instance types and then show how that will impact us in practice.

What is interactive shell and noninteractive shell?

The definition of interactive shell from bash manual is

An interactive shell is one started without non-option arguments (unless -s is specified) and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.

This at first glance looks a little bit complex. To understand that, you need refer to bash manual to know what do '-s', '-c' and '-i' options stand for as well. But that worth a reading and after that, you will get an idea for that.

To make it simple, just try to think the concept of interactive shell as straightforward as what the name indicates. When you're able to enjoy a "interactive" user experience, for example you can type commands and receive feedbacks, then it is mostly probably an interactive shells. When you cannot get that kind of "interactive" user experience, that normally indicates a noninteractive shell. One typical example is execution of shell scripts in which case, when you type commands via keyword, that script cannot get that information you typed.

What is login shell and non-login shell?

Following paragraph from book "How Linux Works" chapter 13.4.1 describes the concept of login shell.

Traditionally, a login shell is what you get when you first log in to a system with the terminal using a program such as /bin/login. Logging in remotely with SSH also gives you a login shell. The basic idea is that the login shell is an initial shell. You can tell if a shell is a login shell by running echo $0; if the first character is a -, the shell’s a login shell.

The behavior of bash for login and non-login is a little different, this sometimes brings weird issues for engineers if they do not know the difference well. One example is some specific command works fine from remote connected SSH terminal but fails to be found if triggered from remote directly e.g. ssh user@host 'command'. The magic behind this is that the former is a login shell and the latter by default is a non-login shell. And the PATH variable is in most cases are different in this two scenarios.

The difference finally comes to "how bash will load startup files for login and non-login shells". That is illustrated in the following picture.

login-shell

Bash manual has very clear description about this as follows. Again this at first glance looks a little bit complex, but worth going through. Important thing to remember is first of all bash do a little bit different things between starting a login shell and starting a non-login shell and second of all login or non-login option could be specified using "-l/--login" option of bash.

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/. profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

When an interactive login shell exits, or a non-interactive login shell executes the exit builtin command, bash reads and executes commands from the file ~/.bash_logout, if it exists.

When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist. This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of /etc/bash.bashrc and ~/.bashrc.

When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed: if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi but the value of the PATH variable is not used to search for the filename.

I believe with these general concepts and a few hands-on practice, you will know this well.

References