Post

6 Parents Children And Environments

6 Parents Children And Environments

6. Parents, Children, And Environments

Shell Are Executable Files

1
2
3
4
5
6
$ cd /bin
$ ls -l bash cat ls grep
-rwxr-xr-x 1 root root 1113504 Jun  6  2019 bash
-rwxr-xr-x 1 root root   35064 Jan 18  2018 cat
-rwxr-xr-x 1 root root  219456 Sep 18  2019 grep
-rwxr-xr-x 1 root root  133792 Jan 18  2018 ls
1
2
3
4
5
$ cat /etc/shells
/bin/sh
/bin/bash
/bin/csh
/bin/zsh
1
2
$ echo $SHELL
/bin/bash
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# Print a prompt
echo -n '$ '
# Read the user's input in a loop. Exit when the user presses Ctrl-D.
while read line; do
 # Ignore the input $line and print a message
 echo "I'm sorry, I'm afraid I can't do that"
 # Print the next prompt
 echo -n '$ '
done
1
2
3
4
5
6
7
$ PS1="%% "
%% ls                                 The prompt has changed
animals.txt
%% echo "This is a new shell"
This is a new shell
%% exit
$

Parent and Child Processes

A running Linux program is known as a process, so you’ll also see the terms parent process and child process.

Every time you run a simple command, you create a child process.

Each child’s environment is copied from its parent’s environment on startup.

1
2
3
4
#!/bin/bash
cd /etc
echo "Here is my current directory:"
pwd
1
2
3
4
5
6
7
8
9
10
$ chmod +x cdtest

$ pwd
/home/smith
$ ./cdtest
Here is my current directory:
/etc

$ pwd
/home/smith

Environment Variables

1
2
3
4
5
6
7
8
9
10
11
$ printenv | sort -i | less
⋮
DISPLAY=:0
EDITOR=emacs
HOME=/home/smith
LANG=en_US.UTF-8
PWD=/home/smith/Music
SHELL=/bin/bash
TERM=xterm-256color
USER=smith
⋮
1
2
3
4
$ title="Efficient Linux"
$ echo $title
Efficient Linux
$ printenv title                               (produces no output)

Creating Environment Variables

To turn a local variable into an environment variable, use the export command:

1
2
3
$ MY_VARIABLE=10                  A local variable
$ export MY_VARIABLE              Export it to become an environment variable
$ export ANOTHER_VARIABLE=20      Or, set and export in a single command
1
2
3
4
5
6
7
8
9
10
11
12
$ export E="I am an environment variable"     Set an environment variable
$ L="I am just a local variable"              Set a local variable
$ echo $E
I am an environment variable
$ echo $L
I am just a local variable
$ bash                                        Run a child shell
$ echo $E                                     Environment variable was copied
I am an environment variable
$ echo $L                                     Local variable was not copied
                                              Empty string is printed
$ exit                                        Exit the child shell
1
2
3
4
5
6
7
8
9
10
$ export E="I am the original value"          Set an environment variable
$ bash                                        Run a child shell
$ echo $E
I am the original value                       Parent's value was copied
$ E="I was modified in a child"               Change the child's copy
$ echo $E
I was modified in a child
$ exit                                        Exit the child shell
$ echo $E
I am the original value                       Parent's value is unchanged

Superstition Alert: “Global” Variables

Child Shells Versus Subshess

1
2
3
4
5
6
7
8
9
$ alias                        List aliases
alias gd='pushd'
alias l='ls -CF'
alias pd='popd'
$ bash --norc                  Run a child shell and ignore bashrc files
$ alias                        List aliases - none are known
$ echo $HOME                   Environment variables are known
/home/smith
$ exit                         Exit the child shell
1
2
3
4
5
6
7
8
9
$ (ls -l)                                      Launches ls -l in a subshell
-rw-r--r-- 1 smith smith 325 Oct 13 22:19 animals.txt
$ (alias)                                      View aliases in a subshell
alias gd=pushd
alias l=ls -CF
alias pd=popd$ (l)                                          Run an alias from the parent
animals.txt
1
2
3
4
5
6
7
8
$ echo $BASH_SUBSHELL         Check the current shell
0                             Not a subshell
$ bash                        Run a child shell
$ echo $BASH_SUBSHELL         Check the child shell
0                             Not a subshell
$ exit                        Exit the child shell
$ (echo $BASH_SUBSHELL)       Run an explicit subshell
1                             Yes, it's a subshell

Configuring Your Environment

File typeRun bySystem-wide locationPersonal file locations (in order invoked)
Startup filesLogin shells, on invocation/etc/profile$HOME/.bash_profile, $HOME/.bash_login, and $HOME/.profile
Init filesInteractive shells (nonlogin), on invocation/etc/bashrc or /etc/bash.bashrc, depending on distro (look in /etc to check)$HOME/.bashrc
Init filesShell scripts, on invocationSet the variable BASH_ENV to the absolute path to an initialization file (example: BASH_ENV=/usr/local/etc/bashrc)Set the variable BASH_ENV to the absolute path to an initialization file (example: BASH_ENV=/usr/local/etc/bashrc)
Cleanup filesLogin shells, on exit/etc/bash.bash_logout$HOME/.bash_logout
1
2
3
4
5
# Place in $HOME/.bash_profile or other personal startup file
if [ -f "$HOME/.bashrc" ]
then
  source "$HOME/.bashrc"
fi

Rereading a Configuration File

1
2
$ source ~/.bash_profile             Uses the builtin "source" command
$ . ~/.bash_profile                  Uses a dot

Q: Why do you source a configuration file instead of making it executable with chmod and running it like a shell script? A: Because a script runs in a child process. Any commands in the script would not affect your intended (parent) shell. They would affect only the child, which exits, leaving you with nothing changed.

Traveling with Your Environment

Version Control: Git Github

This post is licensed under CC BY 4.0 by the author.