Friday, August 31, 2012

Simple RPM for Shell Scripts

Some of the folks down stream from me think that tar archives and customized install scripts were too difficult to deal with. Thus they requested that I begin migrating my install packages to RPMs. I felt that this was not an unreasonable request, thus began a research project trying to learn everything I could. I decided to start with two small projects the first simply two files and the second about twelve.  I found many examples and some good write ups but even the simple examples were more complicated than what I needed. I eventually figured it out and have simplified the process to the following 5 steps, for the most basic install.


Step1: Create a linux user called "rpmbuild "
For various reasons it is best not to do this as the root user.

Step2: Create required directories under the rpmbuild user account

Because I have used this account to create multiple packages I've setup the following directory structure

Shell> mkdir -p /home/rpmbuild/packages/mygreatrpm
Shell> cd /home/rpmbuild/packages/mygreatrpm
Shell> mkdir BUILD RPMS SOURCES SPECS SRPMS

Step3: Copy your Shell scripts to the SOURCES directory
Step4: Create your spec file in the SPECS directory

Shell> vi SPECS/MyScript.spec

#
%define _topdir /home/rpmbuild/packages/mygreatrpm
Name            : MyScript
Summary         : Does something REALLY great
Version         : %{VERSION}
Release         : %{REV}
Group:          : Applications/Databases
License:        : (c) MyCompany
BuildArch       : noarch
BuildRoot       : %{_topdir}/%{name}-%{version}-root

# Use "Requires" for any dependencies, for example:
# Requires        : tomcat6

# Description gives information about the rpm package. This can be expanded up to multiple lines.
%description
This tool is designed to watch your kids, take out the trash, feed the cat and clean the refridgerator.

# Prep is used to set up the environment for building the rpm package
# Expansion of source tar balls are done in this section
%prep

# Used to compile and to build the source
%build

# The installation.
# We actually just put all our install files into a directory structure that
# mimics a server directory structure here
%install
rm -rf $RPM_BUILD_ROOT
install -d -m 755 $RPM_BUILD_ROOT/opt/MyTools
cp ../SOURCES/myscript.dat $RPM_BUILD_ROOT/opt/MyTools/.
cp ../SOURCES/myscript.sh $RPM_BUILD_ROOT/opt/MyTools/.

%post
echo "Installed %{name} scripts to /opt/MyTools"
# Contains a list of the files that are part of the package
# See useful directives such as attr here: http://www.rpm.org/max-rpm-snapshot/s1-rpm-specref-files-list-directives.html
%files
%defattr(755, root, root)
/opt/MyTools/myscript.dat
/opt/MyTools/myscript.sh
# Used to store any changes between versions
%changelog
* Fri Aug 31 2012 firstname lastname
- Initial release.

STEP 5: Create the package
Shell> cd /home/rpmbuild/packages/mygreatrpm
Shell> rpmbuild -bb --define 'VERSION 1.0' --define 'REV 1234' SPECS/MyScript.spec
...snip...
/home/rpmbuild/packages/mygreatrpm/RPMS/noarch/MyScript-1.0-1234.noarch.rpm


Monday, August 27, 2012

Script runs as root but not as crontab? or
Why does my script run as the root user but won't run from cron.daily? or
What user does cron.daily run as?

I recently ran into a problem with a Subversion update script I wished to execute daily. Unfortunately the svn update failed due to a permissions error. This made little sense to me as I believed if I ran the script as root the script should work. It turns out that on some *nix systems (RH Linux and other variants) the root user has a home directory called /root. Within this directory is where the .subversion directory sits which contains your connection information.  Thus solution was to set the HOME variable in my script, as crontab doesn't necessarily pick up environment variables that you get when you log in.

Below you will find the simple fix.


#!/bin/sh
HOME=/root
export HOME=${HOME}
cd /usr/local/svn_workspace/trunk
/opt/CollabNet_Subversion/bin/svn update



Saturday, August 18, 2012

Shell Script Timestamps

Shell Script Trick No. 3 Timestamps
Over the years I've had the need to use time stamps in my scripts to name log files or directories. I created this function to make the task easier.
Usage is as follows:
timestamp "yyyymmdd"
sets the variable $timestamp to 20120818

timestamp "mm/dd/yy"
sets the varible $timestamp to 08/18/2012


##################
# timestamp: This function generates a timestamp
# Calling Profile: timestamp "format"
# Returns:  timestamp
##################
timestamp () {
  format=$1
    yyyy=`date +%Y`
    yy=`date +%y`
    month=`date +%m`
    day=`date +%d`
    hour=`date +%H`
    min=`date +%M`
    sec=`date +%S`

case $format in
     "yesterday yyyy.mm.dd" ) timestamp=`date --date yesterday "+%Y.%m.%d"` ;;
     "yesterday yyyy-mm-dd" ) timestamp=`date --date yesterday "+%Y-%m-%d"` ;;
     "yesterday yyyymmdd" )   timestamp=`date --date yesterday "+%Y%m%d"` ;;
     "yyyy" )                 timestamp="$yyyy" ;;
     "yy" )                   timestamp="$yy" ;;
     "dd" )                   timestamp="$day" ;;
     "mm" )                   timestamp="$month" ;;
     "hh:mm:ss" )             timestamp="$hour:$min:$sec" ;;
     "hhmmss" )               timestamp="$hour$min$sec" ;;
     "mm/dd/yy" )             timestamp="$month/$day/$yy" ;;
     "mm/dd/yyyy" )           timestamp="$month/$day/$yyyy" ;;
     "yyyymmdd"    )          timestamp="$yyyy$month$day" ;;
     "yyyymmddhhmm" )         timestamp="$yyyy$month$day$hour$min" ;;
     "yyyymmddhhmmss" )       timestamp="$yyyy$month$day$hour$min$sec" ;;
     "yyyy-mm-dd" )           timestamp="$yyyy-$month-$day" ;;
     "yyyy.mm.dd" )           timestamp="$yyyy.$month.$day" ;;
     "mmddyyyy"   )           timestamp="$month$day$yyyy" ;;
     "dd/mm/yy"   )           timestamp="$day/$month/$yy" ;;
     "dd-mm-yy"   )           timestamp="$day-$month-$yy" ;;
     "dd-mm-yyyy" )           timestamp="$day-$month-$yyyy" ;;
     "mm-dd-yy"   )           timestamp="$month-$day-$yy" ;;
     "mm-dd-yyyy" )           timestamp="$month-$day-$yyyy" ;;
     "mm dd, yyyy" )          timestamp="$month $day, $yyyy" ;;
             *   )            timestamp="$hour$min$sec";;
esac 
}

Shell script reading files


Shell Script Trick No. 2
Reading files. Over the years I have used a couple of different methods for reading configuration files.
I present the two I have used the most with the second being my current favorite.

cat config | while read line
do
LINE=`echo $line | cut -d: -f2`
if [ "$LINE" = "#" ];then
  echo 
else
  echo "$LINE:\c"
fi
done

#The read command eats leading spaces
exec <  ${datafile}
while read line  
do
 # Don't process lines with comments just skip them. 
 if ( echo $line | grep "^#" > /dev/null 2>&1 );then
   continue
 fi
done

Friday, August 10, 2012

Remove Carriage Return from string variable

Recently I was tasked with writing some scripts to copy log files from a drop site to a working directory then to unzip them. This was not a very difficult task but I ran into a small issue, how to remove a carriage return from a string variable

How to remove a Carriage Return from a string variable?

     #setup     
     logs=`ls`
     #use the tr command and the octal code for CR
     logs=`echo ${logs} | tr -d '\15'`