Tuesday, September 16, 2008

Zero length trustdb.gpg on FAI Debian installs

So...

We had this issue where Debian clients installed with FAI had zero length apt trust databases (/etc/apt/trustdb.gpg). The reason turned out to be the permissions on /etc/apt/trustdb.gpg (0600) in the FAI nfsroot combined with the lack of the no_root_squash option in the FAI nfsroot's /etc/exports line.

In the FAI install, you will notice that your repository is "untrusted." The installed client will have the same issue. When you try to cat or copy /etc/apt/trustdb.gpg from within the installation process, like the FAI process does, you will get an INPUT/OUTPUT error, of course. The root user of the installation has been remapped by the nfs server to nobody.

DOH. Where's Bill Engvall?

Cheers,

Adam

Saturday, August 30, 2008

HTML Grapher in Bash- A bash (awk et al) script for graphing two columns to HTML/CSS


#!/bin/sh
#
# * Copyright (c) 2008
# * Adam Keck. All rights reserved.
# *
# * Redistribution and use in source and binary forms, with or without
# * modification, are permitted provided that the following conditions
# * are met:
# * 1. Redistributions of source code must retain the above copyright
# * notice, this list of conditions and the following disclaimer.
# * 2. Redistributions in binary form must reproduce the above copyright
# * notice, this list of conditions and the following disclaimer in the
# * documentation and/or other materials provided with the distribution.
# * 3. The name Adam Keck may not be used to endorse or promote products derived from this software
# * without specific prior written permission.
# *
# * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# * SUCH DAMAGE.

#Print Usage

usage () {
echo "$0 {-h|-help} {-f |--file=2-column-ACSII-csv-file -o|--outfile=HTML-output-file -c|--colors=comma-separated-list-of-css-colors -bg|--background-color=css-backgroundcolor }"
}

# Make sure file exists and is ASCII

validatefile () {

if [ -z $1 ]
then
usage
return 1
fi

if [ -f $1 ]
then
if [ "`file $1| awk '{print $2}'`" = "ASCII" ]
then
return 0
else
echo "File is not ASCII text." 2>&1
return 1
fi
else
echo "File does not exist." 2>&1
return 1
fi
}

# Get the height of the whole graph by getting the maximum value of column two after stripping out non-numeric characters

graphheight () {
FILE=$1
echo "`awk -F, '{gsub("[^0-9]", "", $2);if($2>a)a=$2}END{print a}' $FILE` * 10 + 30 " | bc
}

# Look up the color from the list of CSS colors supplied on the command line

lookupcolor () {
COLORNUMBER=$1
echo $COLORNUMBER,$2 | awk -F, '{print $($1+1)}'
}


# Process arguments

# If no arguments have been specified on the command line then print the usage

if [ $# = 0 ]
then
usage
exit 1
fi

# Loop through the arguments setting variables used the script.

while [ $# -gt 0 ] ; do

case "$1" in
-f|--file=*)
if [ "$1" = "-f" ] ; then
shift
if validatefile $1
then
INPUTFILE=$1
else
exit 1
fi
else
FILEHOLDER="`echo $1 | sed s,--file=,,`"
if validatefile $1
then
INPUTFILE=$FILEHOLDER
else
exit 1
fi
fi
;;
-o|--outfile=*)
if [ "$1" = "-o" ] ; then
shift
GRAPHFILE=$1
else
GRAPHFILE="`echo $1 | sed s,--outfile=,,`"
fi
;;
-c|--colors=*)
if [ "$1" = "-c" ] ; then
shift
COLORS=$1
else
COLORS="`echo $1 | sed s#--colors=##`"
fi
;;
-bg|--background-color=*)
if [ "$1" = "-bg" ] ; then
shift
BGCOLOR=$1
else
BGCOLOR="`echo $1 | sed s,--background-color,,`"
fi
;;
-h|-help)
usage
exit 0
;;
*)
usage
exit 1
;;
esac

shift

done

# Set some reasonable default colors in case they were not
# specified on the command line.

if [ -z $COLORS ]
then
COLORS=black
fi

if [ -z $BGCOLOR ]
then
BGCOLOR=lightgrey
fi


# Write out the HTML header

echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head> <meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\" /> <title>`echo $INPUTFILE | awk -F. '{print $1}'`</title>" > $GRAPHFILE


# Generate graph

# First, get the number of columns

WIDTH=`cat $INPUTFILE | wc -l `

# write the global CSS

echo "
<style>
h2 {
line-height: 1.5em;
font-family: sans-serif;
font-weight: normal;
}

#vertgraph {
width: `echo "${WIDTH}*55" | bc`px;
height: `graphheight $INPUTFILE`px;
position: relative;
background: $BGCOLOR;
}
#vertgraph ul {
width: `echo "${WIDTH}*65" | bc`px;
height: 200px;
margin: 0;
padding: 0;
}
#vertgraph ul li {
position: absolute;
width: 45px;
bottom: 20px;
padding: 0 !important;
margin: 0 !important;
text-align: center;
font-weight: normal;
font-size: 9px;
color: white;
line-height: 2.5em;
list-style-type: none;
font-family: sans-serif;
}

" >> $GRAPHFILE

echo "
</style>
" >> $GRAPHFILE

echo "</head> <body>" >> $GRAPHFILE

echo "<h2>`echo $INPUTFILE | awk -F. '{print $1}'`</h2>" >> $GRAPHFILE

# Write the graph div

echo "

<div id=\"vertgraph\">
<ul>
" >> $GRAPHFILE

# Initialize the line counter and the position of the first color in
# color list.

LINENUMBER=0
COLORNUMBER=1

# Loop through file creating list elements

cat $INPUTFILE | while read LINE
do

# Remove non-numeric characters from the column two value of each line.
# If no characters remain, set the raw height to .1 so that in the
# creation of the list element for the column, the column will get 1 pixel
# for height

HEIGHTRAW=`echo $LINE | awk -F, '{gsub("[^0-9]", "", $2);print $2}'`
if [ -z $HEIGHTRAW ]
then
HEIGHTRAW=".1"
fi

# Check the color number, i.e. the position in the color list
# from the command line. If it's more than the number of colors
# in the list, reset it to one.

if [ $COLORNUMBER -gt `echo $COLORS | awk -F, '{print NF}'` ]
then
COLORNUMBER=1
fi

# Get the color from the list of colors corresponding to the position in
# the list specified by the value of color number.

COLOR=`lookupcolor $COLORNUMBER $COLORS`

# Write the list element corresponding to the line we are processing in the
# input file. The height of the column will be the second column times 10
# pixels. Each column is placed to right of the last one by 55 pixels.
# The header for the column is the value of the first column.
# The column one value is stripped of all non-alpha numberic characters.

echo "<li style=\"height: `echo "$HEIGHTRAW * 10" | bc`px ; left: `echo "(${LINENUMBER}*50) + 5" | bc`px; background-color: $COLOR;\" >`echo $LINE|awk -F, '{print $1}'|sed 's/\W//g'`</li> " >> $GRAPHFILE

# Increment the counters

LINENUMBER=`expr ${LINENUMBER} + 1`
COLORNUMBER=`expr ${COLORNUMBER} + 1`

done

# Close out the list,div, and HTML code

echo "
</ul>
</div>
" >> $GRAPHFILE

echo "</body> </html>" >> $GRAPHFILE



====================================================

That is, for

A,4
B,5
C,3
D,5

generate a bar graph using only CSS and HTML.

Javascript would have been more useful, but this is a bash blog. If you need javascript, this is "BSD" licensed, so have at it :-).



Cheers,

-Adam

Wednesday, July 9, 2008

Systems Administration Koans [2008]

Some koans...

-----------

A sysadmin asked the Master,

"What's the best way to install a new system?"

The Master answered,

"Turn it on."

The sysadmin was enlightened.

-----------

A sysadmin asked the Master,

"What's the root password to this server?"

The Master asked,

"Do you have access to the console?"

The sysadmin replied,

"Yes."

The Master replied,

"The root password is whatever you want it to be."

The sysadmin was enlightened.

-----------

An sysadmin seeks approval from the Master:

"Master, I have designed and implemented a system with no single points of failure!"

The Master answered, "Have you documented it?"

"Not yet - I wanted to get it done first."

The Master asked, "Give me the name of a team member that can build another one without seeing you or contacting you."

"Well, I can't, yet - I just built it."

The Master answered, "Your system has at least one single point of failure."

The sysadmin was enlightened.

-----------

The Master called the two lead operational sysadmins into the office, asking,

"What is your daily routine?"

The first admin answered,

"First I check to see if my security patches went out, then I push out patches that failed to push the first time, then I ping all the systems to make sure they are up, then I go through the logs for each of my machines to check for issues, then I see if systems engineering has any updates, then I push those, as well; then - "

The Master cut the first admin short, asking the second, "What about you?"

"I have nothing to do," said the second.

The first admin was reprimanded, the second, given a raise.

-----------

The Master asked a junior administrator, "Tell me how your installation system works."

The junior administrator replied,

"First I boot from the network into the automated installation, then the automated post-installation, I wrote, runs, then any post-installation package updates run, then I configure the machine to get updates from my automatic update system. Then I deploy the machine."

The Master replied, "Why waste time on post-installation?"

The junior admin was enlightened.

-------------

The Master asked two junior admins how their weekend upgrades went.

The first related that he sent out his maintenance notice on time, scheduled downtime, and successfully completed every item on his process checklist within his downtime window. His clients were able to restart their applications within the downtime window with no issues. His successfully restored his services before the downtime window ended and sent his completion notice.

The second related that she had sent out her maintenance notice on time, completed every item on her process checklist within her window, and sent her completion notice.

The Masters asked, "You clients said they were not asked to restart their applications and emailed me asking if you actually did your upgrade. What happened?"

The second junior said, "I designed my process so that my services were never interrupted."

The first admin was reprimanded. The second, rewarded.

-------------

A junior admin once inquired of the Master.

"Master, what is the One True Text Editor for finding the One True Path?"

The Master admonished him.

"Your desire to find the One True Path will keep you from finding the One True Path. Go complete your work."

The junior admin was enlightened.

-------------

A Manager once said to the Master,

"I get 100s of resumes a week from people looking for jobs. You are all replaceable."

The Master replied,

"True. Given unlimited time and money, you can replace any employee."

-------------

(c) Adam Keck 2008. All rights reserved. (a0f29b982)

The above post is not licensed in any way.

Thursday, May 1, 2008

Days Between

A little script to tell you the days between two YYYYMMDD dates:

#!/bin/bash

function usage {
  echo "date {date} {date}, where date is in the format YYYYMMDD"
}

function absolute_value {
  echo $1 | sed s/-//
}

# Print help, if number of args wrong

if [ -z $2 ]
then
  usage 1>&2
  exit 1
fi

if [ $3 ]
then
  usage 1>&2
  exit 1
fi

# The dates we want to days between
DATE_ONE="$1"
DATE_TWO="$2"

# provide the original date instead of "now" and ask for "seconds since epoch"

DATE_ONE_EPOCH=$(date -d "${DATE_ONE}" "+%s")
DATE_TWO_EPOCH=$(date -d "${DATE_TWO}" "+%s")

#Math

DAYS=$(($((${DATE_ONE_EPOCH} - ${DATE_TWO_EPOCH}))/$((60*60*24))))

absolute_value $DAYS

------

Note the unmath in "absolute_value" ;-)

Tuesday, April 8, 2008

Linux Live Search...

So... The other day I decided to set up 'locate' to find files in my home network shares, /home/ghostis and /sandbox/ghostis. To do so, I did the following:


% mkdir /home/ghostis/Documents/locate

Added the an updatedb job to my crontab on my laptop:

15,30 * * * * updatedb --netpaths='/home/ghostis /sandbox/ghostis' --output=/home/ghostis/Documents/locate/locatedb --localpaths=' '

Now I can do faster searches of filenames via:

locate -d ~/Documents/locate/locatedb sometextinfilename


But, then I thought, "What's the absurd extreme?"
Linux Live Search!
So I baked a quick bash script:

% cat linux_live_search.sh


#!/bin/bash
clear
echo "Please type something. (Escape spaces. Ctrl-C to quit)"
echo "------------------------------------------"
echo "Query: $WORD"
echo "------------------------------------------"
while read -s -n1 KEY
do
clear
if [ "$KEY" = "" ]
then
WORD=`echo "$WORD"| sed -e 's/.$//'`
else
WORD="`echo "$WORD"`$KEY"
fi
if [ "$KEY" = "" ]
then
unset WORD
fi
if [ -z "$WORD" ]
then
echo "Please type something. (Escape spaces. Ctrl-C to quit)"
else
killall locate > /dev/null 2>&1
locate --all -d ~/Documents/locate/locatedb "$WORD" | head -30
fi
echo ""
echo "------------------------------------------"
echo "Query: " "$WORD"
echo "------------------------------------------"
done




Try not to choke on your coffee...

Cheers,

-Adam

Sunday, January 27, 2008

Terminal Clock

Clock.sh:
 while : ; do sleep 1; clear; date; done