Bash scripting

From The World according to Vissie
Jump to navigation Jump to search
  • Red command prompt

PS1='\[\033[01;31m\][\h]\[\033[01;34m\]\w\$\[\033[00m\] '

PS1="\`apm|awk '\$5~/%/{print \$5}\$6~/%/{print \$6}'\` [\\u@\\h:\\w] \\$ "  (you need to emerge acpi)
-eq is equal to,
-ne not equal to,
-lt less than
-le less than or equal to
-gt greater than
-ge greater than or equal to}}
concat a=abc then a=${a}'123' will give you abc123
len if 'just' a=abc123 echo ${#a} is 6
${a:0:3} first 3 char
${a:-3} lastt 3 char
  • Here is my first script. Lets make sure aMule gets restarted when it fails. We also need to kill aMuleWeb when this happens:
TEST=`ps -A | grep -w ping`
TESTII=`ps -A | grep -w amuleweb | awk '{print $1}'`

if [ -z "${TEST}" ]; then
    echo "Ping Not Running"
    while [ "${TESTII}" ]
        echo "kill amule"
        kill $TESTII
        sleep 5
        TESTII=`ps -A | grep -w amuleweb | awk '{print $1}'`

make sure to give executalbe permission to your scripts...

chmod u+x script1
  • Tips:
    • If... Then... Else
if [ "foo" = "foo" ]; then
   echo expression evaluated as true
   echo expression evaluated as false
    • Awk is a full-featured text processing language...
echo one two | awk '{print $1}'
# one

echo one two | awk '{print $2}'
# two
if [ "$FREE" -le "$MINSPACE" ]; then
       mail -s “Running out of room on $DISC” < sendtext

Where sendtext is just a file with “Running out of space” in it.

vim: /home/
for HDD in $(awk '{print $4}' /proc/partitions); do
        if [ ${#HDD} -eq 3 ]; then
                fdisk -l /dev/$HDD | grep "/dev/$HDD"
                DISP=$DISP" "$HDD
select WORD in $DISP
        echo "You picked $WORD"

Gives you Complete Date & Time of last Portage-Tree sync

cat /var/log/emerge.log|head -$(cat /var/log/emerge.log|grep -n "Sync completed"|cut -d ":" -f1)|grep -e "Started emerge"|tail -1|cut -d " " -f5-8
  • Elapsed time
vim: /home/
#start of script
time_start=`date +%s`

#do stuff
sleep 65

#end of script
time_end=`date +%s`
time_elapsed=$((time_end - time_start))
echo "script executed in $time_elapsed seconds"
echo $(( time_elapsed / 60 ))m $(( time_elapsed % 60 ))s

Bash Color Escape Codes

Below is a quick rundown on how to color output of echo in bash. Echo (echo -e) the following escape codes inside \e[ESCCODEm to colorize text in Bash:

   * Black 0;30
   * Dark Gray 1;30
   * Blue 0;34
   * Light Blue 1;34
   * Green 0;32
   * Light Green 1;32
   * Cyan 0;36
   * Light Cyan 1;36
   * Red 0;31
   * Light Red 1;31
   * Purple 0;35
   * Light Purple 1;35
   * Brown 0;33
   * Yellow 1;33
   * Light Gray 0;37
   * White 1;37

Make sure to use echo -e to enable interpretation of backslash escapes:

echo -e "This is red->\e[00;31mRED\e[00m"

Remove Color

Echo \e[00m to remove text color modifications:

echo -n '\e[00m'

Bash and string manipulations Given:


We can use these expressions:

path = ${foo%/*}

To get: /tmp/my.dir (like dirname)

file = ${foo##*/}

To get: filename.tar.gz (like basename)

base = ${file%%.*}

To get: filename

ext = ${file#*.}

To get: tar.gz

1. $ cp filename filename-old
2. $ cp filename-old filename 

These seem fairly straightforward, what could possibly make them more efficient? Let's look at an example:

1. $ cp filename{,-old}
2. $ cp filename{-old,}
3. $ cp filename{-v1,-v2} 

In the first two examples, I'm doing exactly the same thing as I did in the previous set of examples, but with far less typing. The first example takes a file named filename and copies it to filename-old The second example takes a file named filename-old and copies it to simply filename.

The third example might give us a clearer picture of what's actually occuring in the first two. In the third example, I'm copying a file called filename-v1 to a file called filename-v2 The curly brace ({) in this context, tells bash that "brace expansion" is taking place. The preamble (in our case filename,) is prepended to each of the strings in the comma-separated list found within the curly braces, creating a new word for each string.

Find and replace text between 2 words

sed '/#if ! shopt/,/#fi/{s/#//g}' /etc/bash.bashrc

Construct your prompt specification in pieces, or use intermediate variables, or a combination of both. SSH sets the SSH_CLIENT variable, which indicates where you're logged in from. You can then use the host name to determined where you're logged into.

vim: /etc/bash.bashrc
if [[ -n $SSH_CLIENT ]]; then
  case $HOSTNAME in
    * prompt_user_host_color='1;35';; # magenta on
    *) prompt_user_host_color='1;33';; # yellow elsewhere
  unset prompt_user_host_color;; # omitted on the local machine
if [[ -n $prompt_user_host_color ]]; then
PS1+='\[\e[1;34m\] \w\[\e[1;31m\]$(__git_ps1)\[\e[1;0;37m\] \$\[\e[0m\] '

Like the other one, but you could also use the separate rc file for ssh.

tee -a ~/.ssh/rc
vim: ~/.ssh/rc
<<\SSH_RC \
case $HOSTNAME in
    (host1) sshclr=1;;
    (host2) sshclr=3;;

...and wherever you are assigning your $PS1...

PS1="\[\e[1;$((32+ssh_clr))"'... could leave it in single quotes, too...


...which should underline if the last command executed exited with a non-zero exit code.

I added the ${SSH_CLIENT+ssh:} expansion there to clearly denote @ssh: when connected that way...