Chapter 4 Executing Commands
The main purpose of bash (or any shell) is to allow you to interact with the computer's operating system so that you can accomplish whatever you need to do.Usually that involves lauching programs, so the shell takes the commands you type, determines from that input what programs nee to be run, and lauches them for you.
1.1 Running Any Executable
Use bash and type the name of the command at the prompt
$ someprog
[maxwell@MaxwellDBA test]$ echo $PATH
/home/maxwell/.local/bin:/home/maxwell/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
[maxwell@MaxwellDBA test]$
1.2 Telling If a Command Succeeded or Not
The shell variable $? will be set with a non-zero value if the command fails---provided that the programmer who wrote that command or shell script followed the established convention.
$ somecommand
it works...
$ echo $?
0
$ badcommand
it fails...
$ echo $?
1
$
1.3 Running Serveral Commands in Sequence
$ cat > simple.script
long
medium
short
^D # Ctrl-D, not visible
$ bash ./simple.script
# The third, and arguably best,solution is to run each command in sequence. if you
# want to run each program,regardless if the preceding ones fail,separate them with
# semicolons:
$ long ; medium ; short
# if you only want to run the next program if the preceding program worked, and all the
# programs correctly set exit codes.separate them with double-ampersands:
$ long && medium && short
1.4 Running Serveral Commands All at Once
You can run a command in the background by putting an ampersand (&) at the end of the command line.
[maxwell@MaxwellDBA test]$ long & medium & short
[1] 181971
[2] 181972
-bash: long: command not found
-bash: short: command not found
-bash: medium: command not found
[1]- Exit 127 long
[2]+ Exit 127 medium
[maxwell@MaxwellDBA test]$
[maxwell@MaxwellDBA test]$
1.5 Deciding Whether a Command Succeeds
We can use the exit status ($?) of the cd command in combination with an if statement to di the rm only if the cd was successful.
[maxwell@MaxwellDBA test]$ ls -ltr
total 64
-rw-rw-r-- 1 maxwell maxwell 10 Jul 21 15:39 a.out
-rw-rw-r-- 1 maxwell maxwell 19 Jul 21 15:40 cong.txt
-rw-rw-r-- 1 maxwell maxwell 15 Jul 21 15:40 def.conf
-rw-rw-r-- 1 maxwell maxwell 20 Jul 21 15:40 file.txt
-rw-rw-r-- 1 maxwell maxwell 21 Jul 21 15:41 more.txt
-rw-rw-r-- 1 maxwell maxwell 35 Jul 21 15:42 zebra.list
-rw-rw-r-- 1 maxwell maxwell 36 Jul 21 20:03 lines
-rw-rw-r-- 1 maxwell maxwell 49 Jul 21 20:43 asdfwednnrw2rs2esff.txt
-rw-rw-r-- 1 maxwell maxwell 69 Jul 21 21:09 one.file
-rw-rw-r-- 1 maxwell maxwell 65 Jul 21 21:10 another.file
-rwxrwxr-x 1 maxwell maxwell 126 Jul 22 11:51 ext.sh
-rwxrwxr-x 1 maxwell maxwell 123 Jul 22 12:01 donors.sh
-rw-rw-r-- 1 maxwell maxwell 227 Jul 22 13:27 myscript.sh
-rw-rw-r-- 1 maxwell maxwell 838 Jul 22 16:12 func_choose.sh
-rw-rw-r-- 1 maxwell maxwell 576 Jul 22 16:25 func_choice1.sh
-rw-rw-r-- 1 maxwell maxwell 765 Jul 22 16:36 select_dir.sh
drwxrwxr-x 2 maxwell maxwell 58 Jul 22 17:42 sample
[maxwell@MaxwellDBA test]$ if cd sample; then rm * ; fi
[maxwell@MaxwellDBA sample]$ ls -ltr
total 0
[maxwell@MaxwellDBA sample]$ touch a.txt b.txt c.txt
[maxwell@MaxwellDBA sample]$ ls -ltr
total 0
-rw-rw-r-- 1 maxwell maxwell 0 Jul 22 18:46 c.txt
-rw-rw-r-- 1 maxwell maxwell 0 Jul 22 18:46 b.txt
-rw-rw-r-- 1 maxwell maxwell 0 Jul 22 18:46 a.txt
[maxwell@MaxwellDBA sample]$ cd ..
[maxwell@MaxwellDBA test]$ cd sample; if (( $? == 0 )); then rm * ; fi
[maxwell@MaxwellDBA sample]$ ls -ltr
total 0
[maxwell@MaxwellDBA sample]$
1.6 Using Fewer if Statements
[maxwell@MaxwellDBA test]$ pwd
/home/maxwell/shelllearning/test
[maxwell@MaxwellDBA test]$ ls /home/maxwell/shelllearning/test/sample
a.txt b.txt c.txt d.txt
[maxwell@MaxwellDBA test]$ cd sample && rm *; ls -ltr
total 0
[maxwell@MaxwellDBA sample]$ ls -ltr
total 0
[maxwell@MaxwellDBA sample]$
1.7 Running Long Jobs Unattended
If you want to run a job in the background and expect to exit the shell before the job completes, then you need to nohup the job:
[maxwell@MaxwellDBA test]$ nohup long &
[1] 182259
[maxwell@MaxwellDBA test]$ nohup: ignoring input and appending output to 'nohup.out'
nohup: failed to run command 'long': No such file or directory
[1]+ Exit 127 nohup long
[maxwell@MaxwellDBA test]$
The nohup command simply sets up the child process to ignore hang-up signals. You can still kill a job with the kill command, because kill sends a SIGTERM signal not a SIGHUP signal. But with nohup, bash won’t inadvertently kill your job when you exit. The message that nohup gives about appending your output is just nohup trying to be helpful.
1.8 Displaying Error Messages When Failures Occur
A common idiom among some shell programmers is to use the || with commands to spit out debug or error messages.
[maxwell@MaxwellDBA test]$ cmd || printf "%b" "cmd failed. You're on your own\n"
-bash: cmd: command not found
cmd failed. You're on your own
[maxwell@MaxwellDBA test]$ cmd || { printf "%b" "FAILED.\n" ; exit 1 ; }
-bash: cmd: command not found
FAILED.
logout
[root@MaxwellDBA ~]#
Due to an oddity of bash syntax, the semicolon after the last command and just before the } is required, and that closing brace must be separated by whitespace from the surrounding text.
1.9 Running Commands from a Variable
[root@MaxwellDBA ~]# ls -ltr /tmp/
total 28
drwxr-xr-x 2 root root 6 Jul 18 21:44 dir1
drwxr-xr-x 2 root root 6 Jul 18 21:44 dir2
-rw-r--r-- 1 root root 14 Jul 21 13:32 sample_file
-rw-rw-r-- 1 maxwell maxwell 15 Jul 21 15:35 echo.out
-rw-rw-r-- 1 maxwell maxwell 58 Jul 21 15:44 save.out
-rw-rw-r-- 1 maxwell maxwell 142 Jul 21 19:57 ls.out
-rw-rw-r-- 1 maxwell maxwell 213 Jul 21 20:52 all.out
-rw-rw-r-- 1 maxwell maxwell 194 Jul 21 20:57 alla.out
-rw-rw-r-- 1 maxwell maxwell 134 Jul 21 21:10 cat.out
[root@MaxwellDBA ~]# FN=/tmp/cat.out
[root@MaxwellDBA ~]# PROG=echo
[root@MaxwellDBA ~]# $PROG $FN
/tmp/cat.out
[root@MaxwellDBA ~]# PROG=cat
[root@MaxwellDBA ~]# $PROG $FN
1
23
345
4567
56789
678910
sdjdasfa
sadjajdfc
dfjajdjado
adjajnsojqo
a
ab
abc
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi
abcdefghij
[root@MaxwellDBA ~]#
1.10 Running All Scripts in a Directory
Put the scripts you want to run in a directory, and let bash run everything that if finds.
for SCRIPT in /path/to/scripts/dir/*
do
if [ -f $SCRIPT -a -x $SCRIPT ]
then
$SCRIPT
fi
done