Two types of environment variables in the Bash shell:
- Global variables
- Local variables
Global env vars are visible from the shell session and from any child processes that the shell spawns.
We can look at the global env vars:
printenv
We can display the value using echo:
echo $HOME
Those variables can e seen only in the local process in which they are defined.
There is no command to display only local variabels.
We can use set
to print all variables which includes both global and local environment variables.
Naming covention: Lowercase for user defined variables and upercase for system environment variables.
test=test
echo $test
If we enter another shell the echo will return nothing, since we defined a local variable and not a global one.
We do that by using export
before asigning a variable.
When you start a bash shell by logging into the Linux system, by default Bash checks several files for commands. These files are called startup files. Depending on the method of starting the bash shell certain files are processed.
There are three ways of starting a bash shell:
- As a default login shell at login time
- As an interactive shell that is not the login shell
- As a noninteractive shell to run a script
When you login into the Linux system, the bash shell starts as a login shell.
Order in which the Bash shell processes the files is:
/etc/profile
$HOME/.bash_profile
$HOME/.bash_login
$HOME/.profile
We can also find the /etc/profile.d
directory for programs to set the environment variables without modifying the main file.
This is when you type bash at a CLI or open a GUI terminal.
Bash checks for the ~/.bashrc
file. This file first checks for a common /etc/bash.bashrc
file.
bashrc
does two things:
- Checks for the common file
- Provides a place for the user to enter personal aliases and private script functions
This is the shell that the system starts to execute a shell script. If we want specific commands to run each time a script is started on the system we can set the BASH_ENV to point to a script.
We can set aliases for larger commands using the alias
command
alias -p # list alias values
alias li='ls -il' #setting an alias value
This is treated as a local environment variable, to make it persistive add it to the .bashrc
startup file.
We can run multiple commands separating them with ;
echo test;echo test2
date > today.txt # Creates a file even if exists
date >> today.txt # Appends
To remember: File descriptors
- STDIN (0), STDOUT (1), STDERR(2)
We can pip data using |
.
We can use a text file to run commands. For that we need to employ the so called shebang #!
followed by the shell #!/bin/bash
.
No need to end the file with .sh but its a facto standard.
To run the shell we need to give it exec permissions:
chmod u+x test.sh
./test.sh
Once we execute the script we can't use the local variables in the current shell. If we want to use them we can employ exec
:
exec ./test.sh
We can use echo
We can employ the global env vars in the script employing $GLOBAL
.
Set them test=10
the datatype is automatically determined.
We can pass arguments and reference them using $N
being 1 the first argument and so on. If we try to reference a non-existent argument we won't get an error.
echo -n "Enter your name: " # -n supreses the newline char
read name # Reads the input and asigns it to name var
echo "Hello my name is $name"
We can also employ the -p
option of read:
read -p "Please enter your age: " age
If we want to pass more than one input and asign it to diferent variables we can do that by specifying more variables:
read -p "Complete name": first last
If more that two values are passed, the rest is saved on the last variable specified.
We can limit the time that the script waits for user input using -t
option:
read -t 5 -p "Please enter your name: " name
We can also limit the number of characters with the -nN
option being N the number of chars.
read -n1 -p "Do you want to continue [Y/N] " answer
We can avoid displaying what the user writes on the input using -s
option. What happens is that read
command sets the char color the same as the backgrond.
We can check the exit status of the last command executed using $?
.
To specify an exit code we can employ exit
. If no number is given it exits with 0.
A 0 indicates success while a positive integer indicates error.
We can save the output of a command in a variable using $()
or ``
We can perform math using $[ 25 * 5]
but this does not support floats.
Instead we can employ bc
and save the return value into a variable.
To get the desired number of decimal places we need to use scale
and set it to the number of decimals.
We can then use echo
with the options and finally the expression variable=$(echo "options; expression" | bc)
if [ condition ]
then
commands
fi
Interesting options
-n STR: greater than 0 -z STR: its length is 0 -e file: checks if file exists -s file: checks if file exists and is not empty
case variable in
pattern1) commands1;;
pattern2) | pattern3) commands2;;
*) default commands;;
esac
for variable in series ; do
commands
done
For a range we can employ seq
.
while [ condition ] ; do
commands
done
Two ways of defining functions
function name {
commands
}
name() {
commands
}
We cab use return
to return a value.
Using &
we can run scripts in background mode and a jobid and PID are asigned to the script.
While the background process is still running, it still uses your terminal monitor for output messages.
When the job is finished a Done message is displayed
We can do that more than once and have several jobs active.
To run the process in background even if the session is closed we can use nohup
that tells the process to ignore any SIGHUP signal. The process is dettached from the current terminal monitor and redirects all output generated by the process to nohup.out
file.
nohup ./test.sh &
Using Ctrl+C we can send a SIGINT to the current process running in the shell.
We can stop the process using Ctrl+Z. This sends SIGTSTP. The program is still on memory and we can continue running it from where it left off.
We can check the stopped job using ps au
we can then kill the process kill -9 PID
which sends a SIGKILL.
The PID asigned to the script can be used with $$
We can control jobs using jobs
.
Options:
- -l List the PID along with job number
- -n List only jobs that have changed their status since the last notification from the shell
- -p List only the PIDs of the jobs
- -r List only the running jobs
- -s List only stopped jobs
The +
sign in the job status indicates that this is the default job. The default job is the one used by jobs
command if no jobid is specified. The -
sign indicates that after the default job finishes, this will become the default job.
We can restart stopped jobs using bg
which runs it in the background or with fg
which brings the job to the foreground.
To schedule jobs we can employ at
command or cron
table.
The atd
command runs in the background and checks the job queue for jobs to run. Most Linux distros start this at boot time.
atd
checks a special directory on the system, usually /var/spool/at
for jobs submited using the at
command. It checks the dir every 60 seconds by default.
Format: at [-f filename] time
time can be specified in diferent formats:
- HH:MM, HH:MMPM/AM, a name such as now, noon, midnight or teatime(4PM)
If the hour is past, then is executed the next day at the specified hour.
For date:
- MMDDYY or MM/DD/YY or DD.MM.YY, text date such Jul 4 with or without the year, time increment Now + 25 minutes or 10:15PM tomorrow or 10:15 + 7 days.
There are 26 job queues from a to z. a being the highest priority. By default jobs are sent to the a queue.
We can use the -q
to specify a queue.
When a scheduled job is executed any output destined to STDOUT or STDERR is mailed to the user via the mail system.
If no output is generated by the job then no mail is sent. We can still send the mail using -m
option.
We can employ the atq
command with no options to list pending jobs.
We can employ the atrm
command to remove jobs.
For systemd init systems we can employ systemd-run to run a job at a specific time.
We can use cron
to run a script or command on a regular basis like daily.
An entry format is: min hour dayofmonth month dayofweek command
the month can be specified as a three-character text value like mon.
15 10 6 * * echo "hi"
: this will execute at 10:15 the 6th day of every month.
We can list crontab using crontab -l
or edit the crontab using crontab -e
.