Scripts

From LQWiki
(Redirected from Shellscript)
Jump to navigation Jump to search

Scripts are small programs that are not compiled, but interpreted. They are often written in languages such as Perl, PHP, JavaScript. See here for a list of interpreted languages.

If not specified otherwise, a script is usually written in bash.

Bash scripting

Main article: bash tips

Hello world

The minimal bash script that only outputs "hello world" looks like this:

#!/bin/bash
echo "hello world"

Find out your distribution

Main article: find out your distribution

The following script tells you what distribution you have installed on your computer.

#!/bin/bash
found=0;
if [ -e /etc/SuSE-release ]; then echo "You have a SUSE distro"; export found=1; fi
if [ -e /etc/redhat-release ]; then echo "You have a Red Hat distro"; export found=1; fi
if [ -e /etc/fedora-release ]; then echo "You have a Fedora distro"; export found=1; fi
if [ -e /etc/debian-version ]; then echo "You have a Debian, Ubuntu, Kubuntu, Edubuntu or Flubuntu distro"; export found=1; fi
if [ -e /etc/slackware-version ]; then echo "You have a SlackWare distro"; export found=1; fi
if ! [ $found = 1 ]; then echo "I could not find out your distro"; fi

It looks if the respective files exist (if [ -e /etc/SuSE-release ];) and prints the distribution they flag (using the command echo).

Tonka Script

Changes your console to some other colours.

#!/bin/bash

function tonka {

#   Named "Tonka" because of the colour scheme

local WHITE="\[\033[1;37m\]"
local LIGHT_BLUE="\[\033[1;34m\]"
local YELLOW="\[\033[1;33m\]"
local NO_COLOUR="\[\033[0m\]"

case $TERM in
    xterm*|rxvt*)
        TITLEBAR='\[\033]0;\u@\h:\w\007\]'
        ;;
    *)
        TITLEBAR=""
        ;;
esac

PS1="$TITLEBAR\
$YELLOW-$LIGHT_BLUE-(\
$YELLOW\u$LIGHT_BLUE@$YELLOW\h\
$LIGHT_BLUE)-(\
$YELLOW\$PWD\
$LIGHT_BLUE)-$YELLOW-\
\n\
$YELLOW-$LIGHT_BLUE-(\
$YELLOW\$(date +%H%M)$LIGHT_BLUE:$YELLOW\$(date \"+%a,%d %b %y\")\
$LIGHT_BLUE:$WHITE\\$ $LIGHT_BLUE)-$YELLOW-$NO_COLOUR "

PS2="$LIGHT_BLUE-$YELLOW-$YELLOW-$NO_COLOUR "

}

Get your ip

#!/bin/bash
# get ip
/sbin/ifconfig $1 | grep inet | awk '{print $2}' | sed 's/^addr://g'

To get your Internet address if you are behind a NAT:

## The -n option retrieves the Internet IP address
## if you are behind a NAT
if [ "$1" = "-n" ]
then
  ip=$(lynx -dump http://cfaj.freeshell.org/ipaddr.cgi)
else
  if=$1   ## specify which interface, e.g. eth0, fxp0
  system=$(uname)
  case $system in
      FreeBSD) sep="inet " ;;
      Linux) sep="addr:" ;;
  esac
  temp=$(ifconfig $if)
  temp=${temp#*"$sep"}
  ip=${temp%% *}
fi

printf "%s\n" "$ip"
### CFAJ ###

Connect to a wireless access point (WPA compatible)

Tested in Ubuntu 8.10

#!/bin/bash

#removing possible previous temp file
rm list.temp 2>/dev/null

#scans for wifi connections & isolates wifi AP name
# thanks to jonjgc for the array solution
# thanks to ghostdog74 for the AWK suggestion

eval list=( $(sudo iwlist scan 2>/dev/null | awk -F":" '/ESSID/{print $2}') )

#sets prompt
PS3="Choose wifi connection: "

#tests for number of wifi connections, exits if none
if [ -z "${list[0]}" ]; then
	clear
	echo "No available wifi connection"
	exit 1
fi

#menu of wifi connections
select item in "${list[@]}"; do

#sets essid as value for WIFI variable and displays information about the AP
	wifi=$(echo $item)

	sudo iwlist scan 2>/dev/null | sed -n "/$wifi/, +9p" > list.temp
	echo "$(cat list.temp | sed 's/^[ \t]*//')"

#sets channel as value for CHANNEL variable
	channel=$(grep Channel: list.temp | sed 's/.*Channel://g')

#test for mode, if mode = master, sets MODE variable to managed
	mode=$(grep Mode list.temp | sed 's/.*Mode://g')
	if [ "$mode" == "Master" ]; then
		mode="managed"
	else
		clear
		echo "Cannot connect"
		exit
	fi

#tests for encryption key
	key=$(grep key: list.temp | sed 's/.*key://g')
	if [ $key == "on" ]; then
		echo -n "Enter encryption key: "
		read key
	fi

#checks encryption algorithm
	IE=$(grep IE list.temp | sed 's/^ .*IE: \(...\).*/\1/')

#writes to /etc/network/interfaces file for WPA encryption: essid, key, protocols, etc.
	if [ "$IE" == "WPA" ]; then
		sudo cp /etc/network/interfaces /etc/network/interfaces.bakup
		sudo sed -i 's/iface wlan0 inet manual/iface wlan0 inet dhcp/' /etc/network/interfaces
		sudo sed -i -e "/dhcp/a\wpa-passphrase $key" \
	-e "/dhcp/a\wpa-driver wext" \
	-e "/dhcp/a\wpa-key-mgmt WPA-PSK" \
	-e "/dhcp/a\wpa-proto WPA" \
	-e "/dhcp/a\wpa-ssid \"$wifi\"" /etc/network/interfaces
	sudo /etc/init.d/networking restart
	sudo cp /etc/network/interfaces.bakup /etc/network/interfaces
	sudo rm /etc/network/interfaces.bakup
	exit

	else

#sets the wireless configuration for non WPA: essid, channel, mode, key, etc
		sudo iwconfig wlan0 essid \""$wifi"\" channel $channel mode $mode key $key
		echo "------------------------------------------------"
		echo "Connecting to: $wifi at channel: $channel, mode: $mode"
		echo "------------------------------------------------"

#connects to wifi connection
		sudo dhclient
		exit
	fi
done

Command Line Trash Can

#!/bin/bash
# Script by Jim Collings
# Written Sat Jan 30 14:01:38 EST 2010
# A simple trash script that handles spaces and integrates properly with GUI Trash system.
# Handles spaces properly according to every test I've devised so far. 
 
set -e

TRASHLOC="$HOME/.local/share/Trash"

function move_it {
 COUNTER=0
 TARGET_BASE_NAME=`/usr/bin/basename "$*"`
 TARGET_FILE_NAME="${TRASHLOC}/files/${TARGET_BASE_NAME}"  
 TARGET_INFO_NAME="${TRASHLOC}/info/${TARGET_BASE_NAME}"
 XTENSION=""
 
 while [ -e "${TARGET_FILE_NAME}${XTENSION}" ]
 do    
   let COUNTER+=1
   XTENSION="_${COUNTER}"
 done

OLDDIR=`pwd` 

cd "`dirname "$*"`"
 
 FULLPATH=`pwd`
 FULLPATH="${FULLPATH}/"`/usr/bin/basename "$*"`
 FULLPATH=`echo "${FULLPATH}" | sed 's/ /%20/g'`

 cd "${OLDDIR}"
 
 mv -n "$*" "${TARGET_FILE_NAME}${XTENSION}"
 echo "[Trash Info]" > "${TARGET_INFO_NAME}${XTENSION}.trashinfo"
 echo "Path="${FULLPATH} >> "${TARGET_INFO_NAME}${XTENSION}.trashinfo"
 echo DeletionDate=`date +%Y-%m-%dT%H:%M:%S` >> "${TARGET_INFO_NAME}${XTENSION}.trashinfo" 
}


until [ -z "$1" ]  # Until all parameters used up...
do

      if [ -d "$1" ]; then #its a directory 
	  move_it "$1"
      elif [ -f "$1" ];then #its a file
	  move_it "$1"
	elif [ -h "$1" ];then #its just a link
	  rm -f "$1"
       else
              echo "Error condition: '""$1""' not found." 
              echo "Usage: $0 [Pathnames]"
              echo "Where [Pathname] is a list of space delimited existing files or directories the current user has permissions for." 
              echo "So like this: $0 file1 '""file two with spaces""' directoryOne '""directory two with spaces in the name""' ..." 
              exit 1
      fi

      shift

done
                                         
exit 0

Managing Large Compressed Archives

Assume that we have 3 directories, one of which has large amounts of data in it. We want to create a backup of this directory but we don't want any of the resulting archive files to exceed a certain size. The directories concerned are srcFilesDir, where the files are currently, arcFilesDir, which is where we want to put our archives, and extractedFilesDir which is where we will restore those files to.

tar
Tape ARchive, sticks files together end to end and will also compress them.
split
Will divide an input or file into chunks of an exact size.
cat
Does the opposite of split so it can be used to reassemble split files.


Example:

$ tar cvjpSf - srcFilesDir | split -b 1073741824 - arcFilesDir/largarchive.


The options used here are as follows:

For tar

c - Create an archive.
v - Produce lots of output so that we can see any errors.
j - Compress using bzip2 compression.
p - Preserve permissions and ownerships.
S - Handle "sparse" files effectively.
f - Specifies a file or output. In this case we use "-" so that we can also use a pipe (i.e. "|" ) to route the output through to the split command.


For split

b - Specify the maximum allowable size of the individual files created. In this case we are using one Gigabyte or 1073741824 bytes.


Each of the resulting files will begin with a prefix but will be appended with an alphabetic identifier that will be used by cat later on to reassemble the files in the correct order. If I specify a prefix of arcFilesDir/largarchive. then the data will be stored in the arcFilesDir subdirectory and file names will begin with 'largarchive.' but split will append an identifier after the ".".


$ cat arcFilesDir/* | tar xvjf - -C extractedFilesDir


This command follows many of the same rules. It is an example of how we can later reassemble the split files and restore the compressed data.

Options for tar in this case are:

x - Extract files from an archive.
v - Print lots of information about how things are going.
j - Used with x above, this means uncompress using bzip.
f - Used with x above, this specifies where we are getting our data from. In this case standard input.

Well, that's all I got on this right now. I will warn the reader that some compression programs, like zip / unzip, have very poor Large File support. Part of what spurred this HOWTO into being.

Here is how it all might go together:

[root@kaliklak root]# ls *FilesDir
arcFilesDir: 

extractedFilesDir: 

srcFilesDir:
First.iso  Fourth.iso  Second.iso  Third.iso

So these are the files and directories we will be working with. This isn't the best way to handle CD images but as far as file size is concerned they'll work OK for this example.

[root@kaliklak root]# tar cvzpSf - srcFilesDir | split -b 1073741824 - arcFilesDir/largarchive.
srcFilesDir/
srcFilesDir/Third.iso
srcFilesDir/Second.iso
srcFilesDir/Fourth.iso
srcFilesDir/First.iso

So far, so good. Now lets see if the files are as they should be.

[root@kaliklak root]# ls -l arcFilesDir/
total 2687628
-rw-r--r--  1 root root 1073741824 Jan 21 01:49 largarchive.aa
-rw-r--r--  1 root root 1073741824 Jan 21 01:53 largarchive.ab
-rw-r--r--  1 root root  601946112 Jan 21 01:55 largarchive.ac

Great! Now lets try our extraction.

[root@kaliklak root]# cat arcFilesDir/* | tar xzf - -C extractedFilesDir
srcFilesDir/
srcFilesDir/Third.iso
srcFilesDir/Second.iso
srcFilesDir/Fourth.iso
srcFilesDir/First.iso

Fantastic. So our files have extracted properly. Lets check them against the originals, just to be sure.

[root@kaliklak root]# ls -l srcFilesDir/* extractedFilesDir/*
-rw-r--r--  1 root root  728795136 Jan 20 18:53 srcFilesDir/First.iso
-rw-r--r--  1 root root  728795136 Jan 20 19:07 srcFilesDir/Fourth.iso
-rw-r--r--  1 root root  728563712 Jan 20 18:57 srcFilesDir/Second.iso
-rw-r--r--  1 root root  728563712 Jan 20 19:08 srcFilesDir/Third.iso
extractedFilesDir/srcFilesDir:
total 2849208
-rw-r--r--  1 root root 728795136 Jan 20 18:53 First.iso
-rw-r--r--  1 root root 728795136 Jan 20 19:07 Fourth.iso
-rw-r--r--  1 root root 728563712 Jan 20 18:57 Second.iso
-rw-r--r--  1 root root 728563712 Jan 20 19:08 Third.iso
[root@kaliklak root]#

Notice that the files were written into the subdirectory extractedFilesDir/srcFilesDir. This is because tar stores the directory name unless told to do otherwise.

Everything's cool so we are good to go. :-) edit Comments on other compression protocols

zip - Will compress and concatenate files and store permissions and ownerships but does not support files larger than 2 Gigabytes. Also not self splitting.
tar - Does it all but can be complex to use. Not self splitting. Can use a variety of compression tools.
dar - A "fixed" version of tar. Self splitting is added. Not yet mainstream, though. I'm really itching to try it. :-) Currently however, the -P option seems broken. :-|

Managing JVMs

So if your a Java developer, you probably don't use the etc/alternatives system. At least most that I know, don't. This next script manages a symbolic link such that you can easily switch out JVM's. Just set your ${JAVA_HOME} to ~/bin/java and the script will create a link here.

#!/bin/bash
set -e 

JDKDIR="/opt/jdks/" #Must end in a / 

echo "Available jdks: "
echo

ctr=0

for I in `ls ${JDKDIR} | grep jdk`;do 
if [[ -d ${JDKDIR}${I} ]];then
  let "ctr +=1"
  echo ${ctr}. ${JDKDIR}${I}
fi
done
ctr=0
echo
echo Choose:
read response

for I in `ls ${JDKDIR} | grep jdk`;do

if [[ -d ${JDKDIR}${I} ]];then
  let "ctr +=1"
  if [[ ${ctr} == ${response} ]];then

    rm -f "$HOME/bin/java"
    ln -s "${JDKDIR}${I}/bin" "$HOME/bin/java"

  fi
fi

done

Kerberos Startup Scripts

Tested on Centos 5.5

I built Kerberos from source and needed to run it at boot. Toward that end I wrote these two scripts and used webmin to enable the autostart.
While I understand that chkconfig can and should be used in cases such as these, since I wrote these I figured I'd publish them in case someone else found them useful.

Named /etc/init.d/kdcd
Starts the /usr/local/sbin/krb5kdc proc

#!/bin/sh
# written by John Sullivan 12/29/2010
#	/usr/local/sbin/krb5kdc
# description: Start and stop Kerberos5 krb5kdc process
# processname: krb5kdc

# Source function library
. /etc/rc.d/init.d/functions

# If the executable doesn't exist, then why bother?
test -f /usr/local/sbin/krb5kdc || echo "krb5kdc not found. Exiting script." exit 0

NAME=kdcd
DESC="Start and stop Kerberos5 krb5kdc process"

check_kdc_status()
{
krb5kdc_pid=`ps -C krb5kdc -o pid=`
	if [ -z "$krb5kdc_pid" ]; then
			# krb5kdc is NOT running
			return 2
	fi
	if [ -n "$krb5kdc_pid" ]; then
			# krb5kdc is running
			return 0
	fi
}

case "$1" in
	start)
	echo "Starting krb5kdc... "
		check_kdc_status
		RETVAL=$?
	[ $RETVAL -eq 2 ] && /usr/local/sbin/krb5kdc && echo "  krb5kdc started" || 
		echo "  krb5kdc already running!"
			;;
	stop)
	echo "Stopping krb5kdc: "
		check_kdc_status
		RETVAL=$?
	[ $RETVAL -eq 0 ] && kdc=`ps -C krb5kdc -o pid=` && `kill $kdc` && echo "  krb5kdc stopped" || 
		echo "  krb5kdc was not running!"
		;;
	restart|reload)
		check_kdc_status
		RETVAL=$?
	if [ $RETVAL -eq 2 ]; then 
		echo "  krb5kdc was not running!" && echo "  starting krb5kdc: " && 
		/usr/local/sbin/krb5kdc && kdcpid=`ps x | grep -i krb5kdc | grep -v grep` && echo $kdcpid 
	fi
	if [ $RETVAL -eq 0 ]; then
		echo "  stopping krb5kdc... " && kdc=`ps -C krb5kdc -o pid=` && `kill $kdc` && 
		echo "  starting krb5kdc... " && /usr/local/sbin/krb5kdc && 
		kdcpid=`ps x | grep -i krb5kdc | grep -v grep` && echo $kdcpid
	fi
	;;
	status)
		krb5kdc_pid=`ps -C krb5kdc -o pid=`
		[ -z $krb5kdc_pid ] && echo "  krb5kdc NOT running" || echo "  krb5kdc running"
	;;
	*)
		echo "  Usage: kdcd {start|stop|restart|status}"
		exit 1
esac
exit 0

Named /etc/init.d/kadm
Starts the /usr/local/sbin/kadmind proc

#!/bin/sh
# written by John Sullivan 12/29/2010
#	/usr/local/sbin/kadmind
# description: Start and stop Kerberos5 kadmind process
# processname: kadmind

# Source function library
. /etc/rc.d/init.d/functions

# If the executable doesn't exist, then why bother?
test -f /usr/local/sbin/kadmind || echo "kadmind not found. Exiting script." exit 0

NAME=kadm
DESC="Start and stop Kerberos5 kadmind process"

check_kadmin_status()
{
kadmind_pid=`ps -C kadmind -o pid=`
	if [ -z "$kadmind_pid" ]; then
			# kadmind is NOT running
			return 2
	fi
	if [ -n "$kadmind_pid" ]; then
			# kadmind is running
			return 0
	fi
}

case "$1" in
	start)
	echo "Starting kadmind... "
		check_kadmin_status
		RETVAL=$?
	[ $RETVAL -eq 2 ] && /usr/local/sbin/kadmind && echo "  kadmind started" || 
		echo "  kadmind already running!"
			;;
	stop)
	echo "Stopping kadmind: "
		check_kadmin_status
		RETVAL=$?
	[ $RETVAL -eq 0 ] && kdc=`ps -C kadmind -o pid=` && `kill $kdc` && echo "  kadmind stopped" || 
		echo "  kadmind was not running!"
		;;
	restart|reload)
		check_kadmin_status
		RETVAL=$?
	if [ $RETVAL -eq 2 ]; then 
		echo "  kadmind was not running!" && echo "  starting kadmind: " && 
		/usr/local/sbin/kadmind && kdcpid=`ps x | grep -i kadmind | grep -v grep` && echo $kdcpid 
 	fi
	if [ $RETVAL -eq 0 ]; then
		echo "  stopping kadmind..." && kdc=`ps -C kadmind -o pid=` && `kill $kdc` && 
		echo "  starting kadmind: " && /usr/local/sbin/kadmind && 
		kdcpid=`ps x | grep -i kadmind | grep -v grep` && echo $kdcpid
	fi
	;;
	status)
		kadmind_pid=`ps -C kadmind -o pid=`
		[ -z $kadmind_pid ] && echo "  kadmind NOT running" || echo "  kadmind running"
	;;
	*)
		echo "  Usage: kadm {start|stop|restart|status}"
		exit 1
esac
exit 0

See also