Bash

Scripting with Bourne-Again SHell...

Learning Bash Scripting

I thought of learning bash scripting. I do not know how tough is it gonna be. I have not looked at the whole complicated script at all.
I am gonna begin with a simple bash script.

First I need to locate where my bash interpreter is located.
In my case its located in /usr/local/bin/bash

(manoj@linuxweblog.com)
(~) - which bash
/usr/local/bin/bash
Now I am making a simple bash script that would echo(print a string on my scren)
(manoj@linuxweblog.com)touch first_bash.sh
(manoj@linuxweblog.com)vi first_bash.sh

Get a count of files/folder in a directory

$ ls -A1 /path/to/folder | wc -l

Lists out the files in a directory including hidden files in a single-column format and pipes it through a line count via wc.

Moving files around to include hidden files

Often times when moving files from one directory to another, specifically when dealing with web folders, I have missed out the all important .htaccess hidden files with just the usual `mv source/* destination` command.

Here's a one liner that will include the hidden files too:

$ ls -A <source> | while read i; do mv <source>/"$i" <destination>; done

Easy Drupal maintenance and upgrades

Since Drupal has been coming out with rapid updates, mainly due to security fixes, it's quite cumbersome to have to keep it up to date. However, with the below setup and the script to help with the maintenance, it was a breeze with the last update. The script has been used to upgrade from 5.5 to 5.6 release.

Note: The script does not currently have any checks (extreme alpha stage) and my Drupal installation is not a standard install so usage may vary. Make sure you understand the script prior to running it. Usual disclaimer applies. You will also need root level access to shell to run the script as it is set to change ownership of files and folders using the "chown" command.

My current Drupal install are based on symbolic links for easy maintenance and upgrades. The layout is as below:

/var/www/html, /var/www/html/site_files, /var/www/html/sites are all symbolically linked to the /var/www/drupal-5.x, /var/www/drupal_files, /var/www/drupal_sites respectively where /var/www/html is the web root.

Document Root = /var/www/html            -> /var/www/drupal-5.x
Files Folder  = /var/www/html/site_files -> /var/www/drupal_files
Sites Folder  = /var/www/html/sites      -> /var/www/drupal_sites

Also, any customization to the .htaccess is on top of the default Drupal code. So the script will automatically prepend the data to the upgraded .htaccess file. Since, I also have the gallery module, the .htaccess file is also set to be writable by apache.

Don't forget to set your site in "maintenance mode" with the default theme, and disable all modules prior to the upgrade. Although, I've done some updates with all modules available without any issues. Also, my custom theme resides in the sites folder and stays untouched with the update.

Place the script in "/var/www" (just outside your document root) and run the update via:

# sh ./update_drupal.sh 5.x

Once completed, run update.php to update any changes to the database. Set site back to production mode, re-applying any customization as necessary.

Sending files as mail attachments via the shell

This article shows how to send e-mails from a shell script, including file attachments. It lists different ways (uuencode, MIME), and explains the advantages and disadvantages of each.

There are other great articles and tips on shell scripts at the site!!

cleanup ftp backups with bash shell script

Here's a small bash code snippet to clean up ftp backups maintained by date. Specifically, if using the SysBK to backup to an external server with just ftp access.

It should be run daily via cron and cleans up folders older than 14 days.

#!/bin/bash
# clean_bak.sh
# Cleans up old backup folders from the remote server.

USR=<user>
PSWD=<password>
HOST=<ftp.domain.tld><br />BAK_PATH=</path/to/backups>

LFTP=/usr/bin/lftp
RM_DATE=`/bin/date +%m-%d-%y -d '15 days ago'`

$LFTP << EOF
set ftp:ssl-force true
connect $HOST
user $USR $PSWD
rm -r -f $BAK_PATH/${RM_DATE}
du -h -d 1 $BAK_PATH
quit
EOF

exit 0

The du option will output the space currently being used by the backups.

NOTE: For security reasons, you should use ftps protocol to connect to the remote backup server if possible, and can force it via:

set ftp:ssl-force true

This can also be put in the "~/.lftprc" or "~/.lftp/rc" file.

bash code snippets

This is going to be a collection of bash code snippets:

  1. Check if the user running the script is root:
    # make sure we're running as root
    if [ `id -u` != 0 ]; then { echo "Sorry, must be root.  Exiting..."; exit; } fi
  2. Check the successful execution of previous command:
    if (( $? )); then
        &nbsp;   {
        &nbsp;    &nbsp;    &nbsp; echo "could not executed successfully";
        &nbsp;    &nbsp;    &nbsp; exit;
        &nbsp;   }
    fi;
  3. Check number of arguments:
    # Check for proper number of command line args.

    EXPECTED_ARGS=1
    E_BADARGS=65

    if [ $# -ne $EXPECTED_ARGS ]
    then
      echo "Usage: `basename $0` {arg}"
      exit $E_BADARGS
    fi
  4. Array loops:
    VALUES=("value1" "value2" "value3" "..." "valueN")

    for ((i=0; i<${#VALUES[@]}; i++))
    do
      echo ${VALUES[$i]}
    done

Check for number of arguments in bash

# Check for proper number of command line args.

EXPECTED_ARGS=1
E_BADARGS=65

if [ $# -ne $EXPECTED_ARGS ]
then
  echo "Usage: `basename $0` {arg}"
  exit $E_BADARGS
fi

looping through an array with the for loop in bash

VALUES=(
value1
value2
value3
...
valueN
)

# Alternately:
#VALUES=("value1" "value2" "value3" "..." "valueN")

for ((i=0; i<${#VALUES[@]}; i++))
do
  echo ${VALUES[$i]}
done

Tailing several files...

I wasn't aware you could tail several files until I had to find a way to track what was going on all the virtual web sites:

$ tail -f /home/virtual/*.*/var/log/httpd/*log

If you only want to see the 404 errors:

$ tail -f /home/virtual/*.*/var/log/httpd/*log | grep " 404 "

Comment