[prog] Bash script problem

Dominik Schramm dominik.schramm at slivery.cotse.net
Sat Jan 21 21:03:07 EST 2006


Hi Noir,

Noir <acknak_halflife at yahoo.co.uk> wrote:

> [...]
> In short, the script should grep the output of a
> program, awk for one column & send an email to me if
> anything from that column matches my criteria.

And that's probably what it fails to do, right? It sends you two
emails, one stating that there was a match, and one stating there was
none. 

I'll walk through the script and comment on it. I hope you get the
idea of why it doesn't work the way you want it to.

Some general remarks beforehand:

`foo` actually executes the command foo and returns what foo
outputs to "standard out" (stdout). 

`foo | bar` executes the command foo, pipes its stdout to the command
bar and returns bar's stdout.

You can turn debugging on (which means that every step is echoed to
stdout before it is carried out) by including "set -x" near the top of
your script.

Okay, with that in mind, let's look at the script:

> #!/bin/bash
>
> BINARY="/usr/sbin/binary"
> MAIL="/bin/mail"
> RECPT="acknak_halflife at yahoo.co.uk"
>
> SUB1="Number does match for `hostname`"
> SUB2="Number doesn't match for `hostname`"

As a rule, I don't call external programs more than once if the result
is always the same. Here, "hostname" could be considered a very cheap
external call, so that it's okay to call it twice.

In other cases, I'd do:
HOST=`hostname`
SUB1="Number does match for $HOST"
...

> ERROR_VALUE="No Matching ID Found"

Is this what you'd like to return on stdout or what you'd like written
in the email body in case of mismatch? 

> # grep for specific column
> PROG1="`$BINARY -l | grep -n 1 | awk {'print $7'}`"

This executes "$BINARY -l", greps for a line, takes the seventh
field and stores this field in PROG1.

> # mail me to let me know that it is not working
> PROG_ERR="`$BINARY -l | $MAIL -s "$SUB2" $RECPT`"

This executes "$BINARY -l", sends a mail with subject $SUB2 and the
output of "$BINARY -l" as its body and stores nothing, i.e. the empty
string (because that's what /bin/mail prints to stdout), in PROG_ERR.

> # mail me to let me know that it is working
> PROG_OK="`$BINARY -l | $MAIL -s "$SUB1" $RECPT`"

This executes "$BINARY -l", sends a mail with subject $SUB1 and the
output of "$BINARY -l" as its body and stores nothing, i.e. the empty
string (because that's what /bin/mail prints to stdout), in PROG_OK.

> # the total outout
> PROG3="`$BINARY -l`"

This executes "$BINARY -l" once again and stores the output (stdout)
in PROG3.

> # conditions
> 	if [ "$PROG1" = "0.00" ] || [ "$PROG1" -gt "1000" ]
> || [ "$PROG" = "1000" ]; then

Is this a typo? "$PROG" is not defined anywhere. If you meant "$PROG1"
you can shorten this to:

if [ "$PROG1" = "0.00" ] || [ "$PROG1" -ge "1000" ]; then

"-ge" means "greater than or equal to".

> 	echo $PROG_ERR

This prints nothing, see above.

> 	elif [ "$PROG3" == "$ERROR_VALUE" ]; then

Can the output of "$BINARY -l" really be "No Matching ID found"?

> 	echo $PROG_ERR

This prints nothing, see above.

> 	else
> 	echo $PROG_OK

This prints nothing, see above.

> fi

------ end of your script -------

Now, here's what I think you really want (please correct me if I'm 
wrong): 

* run $BINARY -l and store its output

* search the output for a specific field/column

* check if that column satisfies some inequalities

* send an email with corresponding subject "matches" or "doesn't"
match 

* print the result on stdout

So, here's how I'd rewrite your script -- but there are plenty of
other possibilities.
Note that "$BINARY -l" is called only once:

----- script suggestion ----
#!/bin/bash

BINARY="/usr/sbin/binary"
MAIL="/bin/mail"
RECPT="acknak_halflife at yahoo.co.uk"

SUB1="Number does match for `hostname`"
SUB2="Number doesn\'t match for `hostname`"

ERROR_VALUE="No Matching ID Found"

# the total outout
PROG3=`$BINARY -l`

# grep for specific column
PROG1=`echo "$PROG3" | grep -n 1 | awk {'print $7'}`

# mail me to let me know that it is not working
PROG_ERR="echo \"$PROG3\" | $MAIL -s \"$SUB2\" $RECPT"

# mail me to let me know that it is working
PROG_OK="echo \"$PROG3\" | $MAIL -s \"$SUB1\" $RECPT"

# conditions
if [ "$PROG1" = "0.00" ] || [ "$PROG1" -ge "1000" ]
then
    # possibility 1
    eval $PROG_ERR
    # possibility 2 (my preferred one)
	echo $PROG3 | $MAIL -s "$SUB2" $RECPT
elif [ "$PROG3" -eq "$ERROR_VALUE" ]
then
    # possibility 1
    eval $PROG_ERR
    # possibility 2 (my preferred one)
	echo $PROG3 | $MAIL -s "$SUB2" $RECPT
else
    # possibility 1
    eval $PROG_OK
    # possibility 2 (my preferred one)
	echo $PROG3 | $MAIL -s "$SUB1" $RECPT
fi

----- end of my script -----

Let me know if this helps you or if you have any further questions.

dominik



More information about the Programming mailing list