Introduction
This page is based partly on a tutorial by Alien (alien@ktv.koping.se), my own work and various other sources eg. http://www.linuxhq.com/ldp/howto/Bash-Prompt-HOWTO.html#toc3. Ben Okopnik's page at http://www.linuxgazette.com/issue52/okopnik2.html and http://www.linuxnewbie.org/nhf/intel/programming/introbashscript1.html so there is lots to read!
References
I put these here first as they are an important reference.
Shell command separator/control characters
| = pipe will take the first commands stdout as the second commands stdin.
|| = OR if first command doesn't exit, it will take the second.
|= = OR IS (mostly used in if statements)
&& = AND if first command does exist, it will execute the second one.
! = NOT (mostly used in if statements)
!= = NOT IS (mostly used in if statements)
= = IS (mostly used in if statements)
; = will separate 2 commands as if they were written on separate command lines
$ = prefix to a variable like "$myvar"
$$ = PID of current process (PID == Process ID)
$0 = Shows program that owns the current process.
$# = Shows all arguments.
$? = Any argument (good to use in `if` statements)
# = remmed line, anything on a line after "#" will be overlooked by the script
{ = start braces (starts a function)
} = end braces (ends a function)
[ = start bracket (multiple-argument specifiers)
] = end bracket (multiple-argument specifiers)
* = wild card (* can substitute any number of characters)
? = wild card (? can substitute any single character)
" = quote
' = precise quote. (Will even include "'s in the quote)
` = command quote. (variable=`ls -la` doing $variable will show the dir list)
. = dot will make bash read the variables from a file, ( . .bashrc )
& = and. as suffix to executed file makes it go to the background(./program &)
> = stream director that will start at the top of the file (in if statements)
1> = stdout stream director
2> = stderr stream director
% = job character, %1 = fg job 1, %2 fg job 2, etc.
>> = stream director append to a file
<< = stream director (cat > file << EOF; anything ; EOF)
> = stream director that will start at the top of the file (in if statements < and > may be used as greater-then and lesser-then, as: if [ "$1" >= "2" ])
\ = back-slash, takes away any special meaning with a character,
\$var will not be treated as a variable.
(and a new line will not be treated as a new line)
escape sequences
There are a lot of escape sequences offered by the Bash shell for insertion in the prompt. From the Bash 2.02 man page:
When executing interactively, bash displays the primary
prompt PS1 when it is ready to read a command, and the
secondary prompt PS2 when it needs more input to complete
a command. Bash allows these prompt strings to be cus-
tomized by inserting a number of backslash-escaped special
characters that are decoded as follows:
\a an ASCII bell character (07)
\d the date in "Weekday Month Date" format
(e.g., "Tue May 26")
\e an ASCII escape character (033)
\h the hostname up to the first `.'
\H the hostname
\n newline
\r carriage return
\s the name of the shell, the basename of $0
(the portion following the final slash)
\t the current time in 24-hour HH:MM:SS format
\T the current time in 12-hour HH:MM:SS format
\@ the current time in 12-hour am/pm format
\u the username of the current user
\v the version of bash (e.g., 2.00)
\V the release of bash, version + patchlevel
(e.g., 2.00.0)
\w the current working directory
\W the basename of the current working directory
\! the history number of this command
\# the command number of this command
\$ if the effective UID is 0, a #, otherwise a $
\nnn the character corresponding to the octal number nnn
\\ a backslash
\[ begin a sequence of non-printing characters,
which could be used to embed a terminal con-
trol sequence into the prompt
\] end a sequence of non-printing characters
Test's options
-d check if the file is a directory -e check if the file exists -f check if the file is a regular file -g check if the file has SGID permissions -r check if the file is readable -s check if the file's size is not 0 -u check if the file has SUID permissions -w check if the file is writeable -x check if the file is executableUseful Examples of piping ( | ) and re-direction ( > )
I am assuming you know some basic linux commands and like me want to build on them.
| Can be used for taking outputs of one command to inputs of the next eg. find / -type f -print | xargs grep '192.168.1.100' would find files with '192.168.1.100' in them and dump the valid output onto the screen.
Minor mods
The command could be modified to search for the current directory your in by simply changing / to . eg. find . -type f -print | xargs grep '192.168.1.100'
The command could yet again be modified if you new part of the file name or type you were looking for, eg. find / name '*.txt' -type f -print | xargs grep '192.168.1.100'
The first example gives (or can give) a huge output so modify it with >.
> can be used for taking outputs of one command and redirecting to a file eg. find / -type f -print | xargs grep '192.168.1.100' > search.txt would find files with '192.168.1.100' in them and dump the valid output into search.txt (invalid search errors would still be dumped to the screen).
>> Can be used for taking outputs of one command and redirecting to a file eg. find / -type f -print | xargs grep '192.168.1.100' >> search.txt would find files with '192.168.1.100' in them and dump the valid output into search.txt but appended onto the end of existing data in search.txt.
This command, ls -al |grep '^d' outputs the sub-directories in the present directory only.
This command, ls -al /etc |grep '^d' outputs the sub-directories in /etc.
This command, ls -al / |grep '^d' outputs the sub-directories below /.
This command, ls -al / |grep '^d' > dir.txt outputs the sub-directories below / into a file dir.txt.
If you have not "twigged" grep '^d' looks for any line beginning with d and outputs that line, so all the directories get listed to the screen.
Now this is a little long winded to type so lets create an alias called 'dr' which when we type 'dr' and enter will run; ls -al |grep '^d'.
OK so lets open /root/.bashrc and put try putting this; alias dr='ls -al |grep 'd'' does this look correct? yes it is but it looks a little odd due to all the '' so to make this easier to read for us humans put in alias dr=(ls -al |grep '^d') instead (if you want to), while you are there put in alias mr='ls -al |more' or alias mr='ls -al |more' which ever you want and alias ls='ls -al --color'.
Now log off root with exit and log back in, running dr and mr will show the expected outputs but saves typing! ls -al should now output in color by default (the alias ls='ls -al --color').
Useful Examples of scripting
ok lets make a little bash script to do backups as desired.
#!/bin/bash
cp -i $1 /home/backup
Ok so exit and make the script executable by typing, chmod +x bkup
The first line tells the shell this is a bash script so act accordingly, what happens next is that the bash shell spawns another bash 'child' shell to run the script in, obviously you could call a korn shell or a C shell instead using this line.
The cp -i $1 /home/backup line says copy the file I specify after calling the script to /home/backup, if a file by the same name exists ask me before overriding, (-i achieves this). So I would type bkup file.txt, and file.txt would be saved to $1 for use in the script, then the name in $1 (file.txt) would get copied to /home/backup but if the file.txt exists there the script would ask before overwriting.
The disadvantage of this script is it can only be run once, if we wanted to run this script regularly with cron we would (if we removed -i) replace file.txt (say) each day (say). Now this maybe fine, however we may wnat to make a backup for each day so lets modify the script a bit, to this,
#!/bin/bash
a=$(date +%T-%d_%m_%Y)
cp -i $1 /home/backup/$1.$a
Ok so what we have done here is call the time, day, month and year and stored it in register a$ for future use, then we have appended a$ to $1, which means that we copy file.txt from one place to /home/backup as file.txt with time and date on the end. It should look something like this; file.txt.01:59:31-08_04_2000 and of course it will be in /home/backup/
Ok lets modify this still further, lets make individual directories below /home/backup and store each day's run in it,
#!/bin/bash
a=$(date +%T-%d_%m_%Y)
b=$(date +%d_%m_%Y)
mkdir /home/backup/$b/
cp -i $1 /home/backup/$b/$1.$a
Ok now do you need an explanation in detail? I hope not! :), if so run this and go look at what happens.
Ok, here is another little script,
#!/bin/bash
if test -f /etc/inittab
then
# file exists, so copy and print a message.
cp -i /etc/inittab /home/backup/
echo "Done."
else
# file does NOT exist, so we print a message and exit.
echo "This file does not exist."
exit
fi
OK so now we have looked for an important system file inattab and backed it up to /home/backup/ Lets expand this further, once a directory is created the mkdir command will raise an error if we attempt to run the script again in the same day. So we will construct a script that checks to see if the dir exists and if not create it, then copy the file across if that file exists, here is that script I have called bkup,
#!/bin/bash #this works ! a=$(date +%T-%d_%m_%Y) b=$(date +%d_%m_%Y) if test -d /home/backup/$b/ then echo "dir exists" else mkdir /home/backup/$b/ fi if test -f /etc/$1 then echo "file exists" cp -i /etc/$1 /home/backup/$b/$1.$a echo "file backed up" ls -al /home/backup/$b/ else echo "file does not exist" fiNext we need to change the script to executable with chmod 755 bkup
The command is then ./bkup < name of file to be copied>
Cron
Ok lets edit this script to backup smb.conf every say 5 minutes.
#!/bin/bash #this works ! a=$(date +%T-%d_%m_%Y) b=$(date +%d_%m_%Y) if test -d /home/backup/$b/ then echo "dir exists" else mkdir /home/backup/$b/ fi if test -f /etc/$1 then #echo "file exists" cp -i /etc/smb.conf /home/backup/$b/smb.conf.$a echo "file backed up" #ls -al /home/backup/$b/ else #echo "file does not exist" fiThis file does basically the same thing, it checks for an existing directory makes one if its not present and does a backup, so lets setup crontab to run the script say, every 5 mins (excessive but good to test with),
I have stored the script in /etc/cron.root as this seemed a good idea, by all means use your own directory.
Crontab uses vi as the default editor so lets change that to pico as its easier (but far less powerful, simply type,
export EDITOR=pico
Now type crontab -e This opens a tempory file typically called /tmp/crontab.1022
Now the syntax of the file is 6 columns with the columns seperated by a space, the last "column" is the command to be executed.
Here is the command to run every 5 minutes,
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /etc/cron.root/bkup or every monday at 5.45 AM
45 5 * * 1 /etc/cron.root/bkup
or every monday at 5.45 PM
45 17 * * 1 /etc/cron.root/bkup
A schedule can be disabled using # and comments can be aded using # as well. You can list the cronjobs for that user by typing crontab -l
This page is still under construction