Bash script to swap out, edit host files This is my first useful bash script. It's meant to make it easy to switch between a "work" hosts file (that blocks sites like reddit.com, youtube.com, etc.) and my normal hosts file, and also to allow me to easily add/remove sites I want to block.

I'm not sure if I'm doing everything right or securely, so please feel free to pick at anything.

#!/bin/bash

usage()
{
cat &lt;&lt;EOF
Usage: wrk [command] [host1 host2 ...]

Commands:
    list                list blocked hosts
    add [host ...]      add a host to be blocked
    rm [host ...]       remove hosts from block
    start               start blocking
    stop                stop blocking
EOF
}

VARDIR="$HOME/abes_commands/var"    
# HOST_FILE - actual host file to be swapped around.
# ORIG_FILE - original host file without any of the appended blocked hosts.
# BLCK_FILE - list of blocked hosts.
# BLCK_TEMP - temporary file used when removing hosts.
HOST_FILE="/etc/hosts"
ORIG_FILE="$VARDIR/original_host"
BLCK_FILE="$VARDIR/blocked_host"
BLCK_TEMP=`mktemp -t "blocked_hosts"` || `mktemp /tmp/blocked_hosts.XXXXXXX` || exit 1

# Make sure files exist.
[[ -e $ORIG_FILE ]] || touch "$ORIG_FILE"
[[ -e $BLCK_FILE ]] || touch "$BLCK_FILE"

# Check to see if the block is currently active.
ACTIVE_FLAG="$HOME/.wrk_block.flag"
if [[ -e $ACTIVE_FLAG ]]; then 
    IS_ACTIVE=0
else 
    IS_ACTIVE=1
fi

add_host()
{
    local hosts=("$@")
    for host in "${hosts[@]:1}"; do
        # append host to blocked hosts list
        echo "127.0.0.1 $host" &gt;&gt; "$BLCK_FILE"
        echo -e "\033[0;32madded\033[0m $host" 
    done
}

# todo: remove need for loop; do in one go
rm_host()
{
    local hosts=("$@")
    for host in "${hosts[@]:1}"; do
        # overwrite host list file with a copy removing a certain host
        awk -v host=$host 'NF==2 &amp;&amp; $2!=host { print }' "$BLCK_FILE" &gt; "$BLCK_TEMP"
        mv "$BLCK_TEMP" "$BLCK_FILE"
        echo -e "\033[0;31mremoved\033[0m $host" 
    done
}

check_root()
{
    if [[ "`whoami`" != "root" ]]; then
        echo "You don't have sufficient priviledges to run this script (try sudo.)"
        exit 1
    else 
        [[ -e $HOST_FILE ]] || { echo "Can't find or access host file."; exit 1; }
    fi
}

start_block()
{
    if [[ $IS_ACTIVE -ne 0 ]]; then
        cp "$HOST_FILE" "$ORIG_FILE"
        cat "$BLCK_FILE" &gt;&gt; "$HOST_FILE"
        touch "$ACTIVE_FLAG"
        echo "Block started."
    else
        echo "Already blocking."
    fi
}

stop_block()
{
    if [[ $IS_ACTIVE -eq 0 ]]; then
        cp "$ORIG_FILE" "$HOST_FILE"
        [[ -e $ACTIVE_FLAG ]] &amp;&amp; rm "$ACTIVE_FLAG"
        echo "Stopped blocking."
    else
        echo "Not blocking."
    fi
}

case $1 in
    'ls' | 'list') 
        awk 'NF == 2 { print $2 }; END { if (!NR) print "Empty" }' "$BLCK_FILE";;
    'add') 
        [[ -z $2 ]] &amp;&amp; { usage; exit 1; }
        add_host $@;;
    'rm' | 'remove') 
        [[ -z $2 ]] &amp;&amp; { usage; exit 1; }
        rm_host $@;;
    'start') 
        check_root
        start_block;;
    'stop') 
        check_root
        stop_block;;
    *)
        usage;;
esac


The blocked_host file is appended to the hosts file when blocking starts, and looks like this:




127.0.0.1 www.reddit.com
127.0.0.1 reddit.com
127.0.0.1 www.news.ycombinator.com
127.0.0.1 news.ycombinator.com
I think this is generally clean.

Style Points

use $() instead of ``, it's clearer and they can be nested.

E.g:

if [[ "$(whoami)" != "root" ]]; then
    echo "You don't have sufficient priviledges to run this script (try sudo.)"
    exit 1


Consider setting:

set -u #prevent unset variables
set -e #stop on an error


At the top of your script.

rm_host may benefit from rewriting using an inplace sed edit, rather than using awk to copy over the top of the old file.

Locks

Although unlikely, you may want to consider a lock to prevent races between add_host and rm_host. $ACTIVE_FLAG would make a good lock.

$VARDIR

It looks like you intend this script to be used at differing privileges level (e.g. root and non-root). This will change the $HOME env variable and consequently the $VARDIR env variable. Potentially {add,rm}_host may act on different files to {start,stop}_block. Note that this won't present itself  if you only use sudo. 

Reconsider what you want $VARDIR to be. On a a single user machine /var/ may be a good choice.