Hey There,
For our "Lazy Sunday" Post this week, we're going to look at some more, hopefully, useful and easy html creation, like we've done many times in the past with posts on listing out Linux or Unix crontabs and a few others. Today's Bash shell script will produce an index.html file (and a whole lot of others) that should end up as your one-stop-shop for the documentation that came with your system's Perl distribution. It's nothing fancy (although you can make it that way if you want) but it should serve its purpose well enough right out-of-the-box.
Of course, you should edit the POD_HTML_DIR variable, at the least, so that the script can find your Perl modules and use pod2html to convert them. Other than that, running it straight-up, like so:
host # ./pods.sh
should produce output like below, in the following two pictures (click on them to make them larger if you need to :)

Hope you enjoy the script and it brings you some convenience! Note that I'm 100% aware that there is no error handling done for files that can't be created (i.e. when pod2html fails, a blank html page is hyperlinked to rather than no hyperlink, or html, being created), but that should make the whole experience more educational if you want to add that. You can refer to our earlier posts on Bash's implementation of errno and the Bash-specific PIPESTATUS variable to help handle those errors and do what you want with them ;)
Happy Sunday,
This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License#!/bin/bash
#
# pods.sh - make perdocs into one html repository
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#
trap 'cd $PWD;rm -rf $POD_HTML_DIR;exit 2' 1 2 3 15
PWD=`pwd`
PERL_MANPAGE_BASE=/usr/lib/perl5/5.8
POD_HTML_DIR=podhtml
INDEX_PAGE=index.html
if [ -d $POD_HTML_DIR ]
then
rm -rf $POD_HTML_DIR
fi
mkdir podhtml
echo -n "Working on it..."
find $PERL_MANPAGE_BASE -name "*.pm"|while read line do
do
echo -n "."
output=`echo $line|sed 's/^.*\/\(.*\)$/\1/'`
pod2html $line >podhtml/${output}.html 2>/dev/null;
done
cd $POD_HTML_DIR
echo "<html><head><title>Perl Module Document Repository</title></head><body>" >$INDEX_PAGE
ls |grep html|while read line
do
echo "<a href=\"$line\">$line</a><br>" >>$INDEX_PAGE
done
echo "</body></html>" >> $INDEX_PAGE
echo "done"
, Mike
Sunday, June 29, 2008
Fast Perl HTML POD Creation On Linux and Unix
Thursday, December 20, 2007
Getting Error Values From The Middle Of A Pipe Chain In Bash
This is something very interesting I found out not too long ago, while hashing out some work with a colleague. As most administrators (or users) who do a fair amount of shell scripting know, the error status or return code (Generally referred to as "errno" in all the man pages) of a process is a fairly common method to use in determining the process flow of a script.
The one thing about the value of "errno" (or, literally, the variable "$?" in most shells) is that it's erased with each consecutive process that gets run. So if you were to run a series of command lines that echoed the return value of the grep command, the following example would be accurate (assuming the string "bob" can't be found in /home/myfile):
host # grep bob /home/myfile >/dev/null 2>&1
host # echo $?
host # 1
while this one would give you misleading information:
host # grep bob /home/myfile >/dev/null 2>&1
host # touch /home/myfile
host # echo $?
host # 0
So, on the first set of command lines, you're actually getting the return code of 1 from grep (indicating that it can't find the string "bob" in /home/myfile), while the second one gets you the return code of 0 from the touch command. "errno" always contains the return value of the last-executed command.
Which brings us around to the topic indicated in the title of this post (I promise to tie in the whole introduction about "errno" at the end; it wasn't a complete waste of your time ;). While it's easy enough to trap "errno" in any series of disconnected commands (for instance, in the second example above, if we'd echoed $? before running touch, it would have given us the correct output), I had always thought it was impossible to grab the correct value from a command in the middle of a pipe chain, like this:
host # grep bob /home/myfile 2>&1|Grep joe|xargs echo
host # echo $?
host # 0
You'll note that I purposefully capitalized the G in grep so that it would return an error code that didn't indicate success, yet - since this is a chain of commands all connected by pipes - "errno" returns the value of the xargs command, since it was the last one executed. Which means I've spent a lot of time jumping through hoops to "reword" any pipe chain so that I could extract the information I needed.
Now (and I'm almost positive this wasn't the case a few years back) the bash shell has actually taken on this predicament and come up with a nice workable solution for it(I'm waiting for it to pop up in sh and ksh, since they've been burned into my psyche over the last decade or so). In bash, if you run a series of piped-together commands, you can actually extract the value of "errno" from any command in the chain by using the shell built-in PIPESTATUS array, like so:
host # grep bob /home/myfile 2>&1|Grep joe|xargs echo
host # echo ${PIPESTATUS[@]}
host # 1 127 0
How nice is that? :) Now you can easily tell the return value of every process in a pipe-chain. The initial grep returns 1 because the string "bob" isn't in /home/myfile, the misspelled Grep returns 127 because the command can't be found and the final xargs returns 0. That solves a lot of problems and can potentially save you lines upon lines of convoluted code.
The one thing about it that can be frustrating is that it behaves in much the same way as "errno" (See, I told you I'd bring it back around ;). If you don't capture the output immediately (or dish it off into another variable), the array will zero out and contain no values as soon as you enter your next command, like so:
host # grep bob /home/myfile 2>&1|Grep joe|xargs echo
host # touch /home/myfile
host # echo ${PIPESTATUS[@]}
host # 0
At this point, after we've executed the touch command, the PIPESTATUS array has been cleared out, just like "errno" gets written over, even though we haven't executed another pipe chain. Its behaviour is basically identical. Below, we show that, once the array has been written over, its size gets reduced to 1 ( The single return value of the last executed command) and we further prove that the array really has been clipped down to one variable by attempting to print the first and second values; the second of which doesn't exist. Continued from above:
host # echo ${#PIPESTATUS[@]} <--- Here we ask bash for the size of the PIPESTATUS array
host # 1
host # echo ${PIPESTATUS[0]} <--- Here we check the first variable in the PIPESTATUS array
host # 0
host # echo ${PIPESTATUS[1]} <--- Here we check the second variable, which now doesn't exist
host #
This is easy enough to get around, however, since - just like "errno" - you can assign that array to another array before you execute another command, like so:
host # grep bob /home/myfile 2>&1|Grep joe|xargs echo
host # new_array=${PIPESTATUS[@]}
host # touch /home/myfile
host # echo ${PIPESTATUS[@]}
host # 0
host # echo ${new_array[@]}
host # 1 127 0
If you knew this already, I envy you the convenience you continue to enjoy. For the rest of us; a pleasant surprise :)
Best Wishes,
, Mike
linux unix internet technology
Posted by
Mike Golvach
at
12:40 AM
administration, advice, array, bash, chain, errno, error, grep, linux, pipe, pipes, PIPESTATUS, return code, return value, scripting, status, technology, tips, tricks, xargs





