Archive

Archive for the ‘Bash’ Category

Print color in shell terminal

January 25, 2012 Leave a comment

Sometimes you might want to print something with color in a text terminal (by color I mean something other than the default text color). Put the following shell function to your ~/.bash_profile and you are go to good.

cecho() {
    case $2 in
        red) code=31;;
        blue) code=34;;
        green) code=32;;
        cyan) code=36;;
        purple) code=35;;
        brown) code=33;;
        white) code=37;;
        *) code=30;;
    esac
    printf "\e[01;${code}m$1\e[0m\n"
}

Some examples:

cecho hello cyan
cecho "something needs your attention" brown
cecho "there's something terribly wrong, have to abort now" red
cecho "this looks so pale" white
cecho "will purple work too?" purple
cecho goodbye blue

The above commands should output something like this ($TERM setting xterm-256color, tested on both OS X 10.7.2 and Ubuntu 11.10 64bit Server):

Advertisements
Categories: Bash, Programming

Combine regular expression and conditional statements in BASH

January 1, 2012 2 comments

As we all know we can use conditional statements in BASH. For example, show usage if number of arguments is 0:

#!/usr/bin/env bash
if [ $# -eq 0 ]; then
    echo "Usage: $0 start|stop|restart"
    exit 0
fi
echo "going to run with \$1=$1"

We might also want to use regular expression to test if $1 is start, stop or restart if $# is no longer 0:

#!/usr/bin/env bash
function usage() {
    echo "Usage: $0 start|stop|restart"
}
if [ $# -eq 0 ]; then
    usage
    exit 0
fi

if [[ ! $1 =~ ^(start|stop|restart)$ ]]; then
    usage
    exit 0
fi
echo "going to run with \$1=$1"

But wouldn’t it be nice if the tests can be combined together. With bash operator || the above code can be written as:

#!/usr/bin/env bash
function usage() {
    echo "Usage: $0 start|stop|restart"
}   
if [ $# -eq 0 ] || [[ ! $1 =~ ^(start|stop|restart)$ ]]; then
    usage
    exit 0
fi  
echo "going to run with \$1=$1"

One more example using operator && instead:

#!/usr/bin/env bash
if [ -d ~/a_folder ] && [[ $1 =~ ^(install|remove)$ ]]; then
    echo "going to $1 something" 
else
    echo "Folder ~/a_folder doesn't exist or you specified the wrong parameter:"
    echo "Usage: $0 install|remove" 
    exit 0
fi  
Categories: Bash, Programming

Replace if … then … fi with && and || in Bash

October 1, 2011 4 comments

&& and || are the shorthand of if … then … fi in Bash. They
are very useful in writing simple scripts, for example:

1. Run script based on day of week:

[ $(date +%w) -eq 6 ] && echo "do something on Saturdays" || echo "do different things on other days"

The equivalent if block of the above would be:

if [ $(date +%w) -eq 6 ]; then
    echo "do something on Saturdays"
else
    echo "do different things on other days"
fi

If more commands are needed when if condition matches (or doesn’t match), you can use { } to put the commands together

[ $(date +%w) -eq 6 ] && {echo "do something on Saturdays"; do_some_other_stuff; exit 0;} || echo "do different things on other days"

The shorthand also makes it easier to write stuffs to crontab, for example, we can put the something like this to crontab

1 8 * * * [ $(date +\%d) -eq 1 ] && ~/scripts/run_stuff_on_first_day_of_a_month

The ‘%’ is escaped, you can check out my another post regarding this.

2. Make sure a specific mount exists
Sometimes we need to make sure a mount point exists before any other tasks can be performed, it’s quite simple to do it with the shorthand form of conditional block:

mount|grep -q "^/dev/sdb1 " || mount /mnt/datastore

This will ensure partition /dev/sdb1 will be mounted to /mnt/datastore. A couple of things are worth pointing out:
1) grep option -q will suppress std output from grep, results are stored in $?, from which operator || will determine to run “mount /mnt/datastore” or not.
2) ^/dev/sdb1 instead of /mnt/datastore is used for the regular expression to eliminate false match. It’s unlikely but possible that the following mount point might exists
/dev/somepartition on /mnt/datastore 2 (ext3, local …)
An additional space is inserted to the end of the regexp in case there are partitions such as /dev/sdb1X (x=0-9) mounted.

3. Make sure a specific folder exists, if not, create it before script runs. For example:

[ -d /tmp/mydir/work ] || mkdir -p /tmp/mydir/work
Categories: Bash, Programming, Tip

crontab editor

September 10, 2011 Leave a comment

To use your favoriate editor to modify user’s crontab, here’s how:

1) Quick and dirty solutions

   EDITOR=vim crontab -e

or

   export EIDTOR=vim
   crontab -e

2) Permanent solution:
add the following line to either ~/.bashrc or ~/.bash_profile

export EDITOR=vim
Categories: Bash, crontab

A few wget tips

June 2, 2011 Leave a comment

In *nix world, wget is a very handy tool to download files from remote ftp or http servers. This post will present a few wget tips that I use quite often in my (mostly Bash) scripts:

1) use –quiet option to surpress download progress indicator
wget --quiet http://host_name_of_the_server/path/to/afile.doc

2) use -N to get file only when timestamp or size of the file downloaded has changed
wget -N http://host_name_of_the_server/path/to/somefile.dat
If file somefile.dat has been downloaded and file size and/or timestamp has not changed on the remote server, downloading of the file somefile.dat will be skipped to save bandwidth (and disk io).

3) when running wget under bash, one can take advantage of Bash curl braces expansion and do something like this
wget http://host_name_of_the_server/path/to/{file1.txt,file2.txt,file3.txt}
or
wget http://host_name_of_the_server/path/to/{file1,file2,file3}.txt
or even
wget http://host_name_of_the_server/path/to/file{1,2,3}.txt

Each of the above commands is equivalent to the following
wget http://host_name_of_the_server/path/to/file1.txt
wget http://host_name_of_the_server/path/to/file2.txt
wget http://host_name_of_the_server/path/to/file3.txt

With less code you get more done.

Categories: Bash, Tip, wget

Change Centos ssh shell color

May 29, 2011 4 comments

When trying to ssh to Cento servers (Versions 5.X, haven’t tried other versions yet), the default directory color blue doesn’t work well with terminals such as Mac OSX Terminal using dark-background and Windows ssh client Putty. I haven’t found a way to change the directory color for a specific user but one to change for ALL users including root. So if you have root access and cannot stand for the hard-to-read color combinations, do the following

1) Edit /etc/DIR_COLORS as root
2) Locate line
DIR 01;34 # directory
and change it into
DIR 01;33 # directory

3) Save the file
4) Do the same steps for file /etc/DIR_COLORS.xterm
5) New logins can now see the new directory color

What step 2) does basically is changing the directory color from blue into yellow (it actually looks golden on black background). Step 1-3 take care of Mac OSX Terminal using Homebrew scheme, step 4 is needed if there are putty users.

EDIT [ 06/07/2011 ]:
Just found the answer to changing dir colors for a specific user here:
http://linuxtoolkit.blogspot.com/2009/06/painting-ls-on-bash.html

Categories: Bash, ssh, Tip

Diff text file remotely with local file

May 16, 2011 Leave a comment

Found a pretty neat solution at http://www.genlinux.org/2009/04/remote-diff-in-linux.html for comparing remote and local files. For example, if I want to compare the file

remote_ip:~/myscript.sh with the local version, I no longer have to copy the remote file to a temporary location and do a local diff, instead, with the solution provided in the link above, I can simply do


ssh user@remote_ip 'cat ~/myscript.sh' | diff - path/to/local/myscript.sh
Categories: Bash, linux, Tip