shell script help

Michael Velez mikev777 at hotmail.com
Fri Aug 19 22:33:17 UTC 2005


>       I am hoping that someone here can help me with a shell
> script.  I can do this in PHP but am trying to learn how to
> script better in a shell script.
>       What I am trying accomplish here is to get all of this
> into one script and do it more efficiently:
> 1.  Get all db.domainname.extension files in the /var/named
> directory 2.  Replace any occurance of a line that starts
> with "mail\s\+A\s\+192.168.22[4-5].*" with "mail\t\t\tA\t192.168.1.4"
>       2.a.  For testing, I am copying these to another
> directory first and doing all work in the test directory
> until the script works perfectly.
> 3.  If the file gets changed, I need it to put the file name
> without the leading "db." into test.txt in the following format:
>       to:domainname.extension                   RELAY
> 4.  If the file already has the line of
> "mail\s\+A\s\+192.168.1.4" in it, then I need it to also put
> that into the test.txt file in the same format.
>       to:domainname.extension                   RELAY
> 5.  If the file has anything but the "192.168.22[4-5].*" or
> "192.168.1.4" IP's for that line, then I don't want it to
> change it and I don't want to record it in the test.txt file.
>
> This script is going to change all of the dns records so that
> the mail.domainname.extension will point to our new email
> server.  I want to get it automated so that if anybody sets a
> site up in our Ensim control panel, it will make these
> changes and then I can create a script that will move the
> test.txt file over to the email server in an "access" file,
> then make the access.db and restart sendmail/MailScanner.  I
> will eventually test to see if there are any changes in the
> old and new access files and if not, it won't restart
> sendmail/MailScanner.  I figure that I will run this twice a day.
>
> Right now, I am doing this in two separate scripts and it
> doesn't do everything I want here anyway.
> Here is what I have so far:
> ----start test.sh file----
> #!/bin/sh
> cp -pf /var/named/db* .
> for i in `ls db.*`
> do
> echo $i
> mv $i $i.$$
> sed
> 's/mail\s\+A\s\+192.168.22[4-5].*/mail\t\t\tA\t192.168.1.4/'
> $i.$$ > $i rm $i.$$ done ----end test.sh file----
>
> ----start test2.sh file----
> #!/bin/sh
> for i in `ls db.*`
> do
> echo $i
> grep -H 'mail\t\t\tA\t192.168.1.4'
> rm $i.$$
> done
> ----end test2.sh file----
>
> Thanks in advance for any help.
> Steve
>

Great example for regular expressions.

Since it's short and straightforward, I took the liberty of writing
something, since I work for myself at home.  And I'm always willing to help
somebody out in the learning process (see NOTES below).  That said, I got
caught up in grep's strange '\' behavior.

Disclaimer: This is probably not the complete script and I only tested the
sed and grep lines (it probably will not work as it's written but should be
close). And Steve, I know I don't need to tell you that you need to be
comfortable with this script (that it does what you need and only what you
need) before using it.

#!/bin/bash

for FILENAME in `ls db.*`
do
        mv $FILENAME $FILENAME.$$

        sed -r
's/^mail\\s\\\+A\\s\\\+192.168.22[4-5].[0-9]{1,3}/mail\\t\\t\\tA\\t192.168.1
4/' $FILENAME.$$ > $FILENAME

        EXISTS1=`grep -c -E
'^mail\\\s\\\\\+A\\\s\\\\\+192.168.22[4-5].[0-9]+' $FILENAME.$$`
        EXISTS2=`grep -c '^mail\\\s\\\+A\\\s\\\+192.168.1.4' $FILENAME.$$`

        if [[$EXISTS1 -ne 0]] || [[$EXISTS2 -ne 0]]
        then
                TRUNCNAME=${FILENAME:3}
                echo "to:$TRUNCNAME\t\tRELAY" >> test.txt
        fi

        rm $FILENAME.$$
done   

I think this is close to what you want.  If not, it should provide the
structure.

Good luck,
Michael

NOTE1: The sed line uses the '-r' option (-E for grep), meaning use extended
regular expressions as opposed to basic (in extended regular expressions,
characters such as '{', '}', '+' etc... have special meaning).  For the last
IP subsegment, I use [0-9]{1,3} in the sed pattern, meaning match a digit
with a minimum of 1 occurrence and a maximum of 3 occurrences. This is
important to make sure the IP address and nothing after the IP address gets
changed by sed.  I don't know the format of this file so if there is nothing
after the IP address, you can simplify this. If there is, '.*' as you used
it in your script, will not produce what you're expecting.
NOTE2: Since extended regular expressions are used for sed, a '+' sign must
be preceded by a '\' to remove its special meaning.  For that matter, a '\'
also needs to be preceded by '\'.
NOTE3: In the 'sed' replacement pattern, I'm assuming you actually want to
insert the two literal characters '\t'. If you only want to insert a tab,
use '\t' instead of'\\t'.
NOTE4: Typing the grep lines on on the command line, '\' behavior is exactly
like for sed.  However, in a script, an extra '\' needs to be added. I could
somehow understand this (due to shell invocation for scripts) but then why
does sed not exhibit the same behavior? I don't know. Maybe the gremlins
have played around with my system. Check this out.
NOTE5: In the two greps, I have not delimited the IP address at the end
which for the second grep, you may need to do, depending on the IP address
on your local network (can .4 be confused with .41?).  You may need to
change those two matching patterns.
NOTE6: The matching pattern for the 192.168.1.4 grep in your explanation
text was different from the one in your script.  Check this out. 
NOTE7: TRUNCNAME=${FILENAME:3} truncates the first 3 characters of FILENAME
and puts it in TRUNCNAME.  The bash man page has great parameter
manipulation under "Parameter Expansion".  I use them all the time.  Check
it out.  Also, the bash man page is the best source for tips and tricks,
although it is about 40 pages of very dense reading and is probably only
really useful when you already know scripting. 
NOTE8: With Unix/Linux scripts, things are usually fairly simple, as
structure should be.  If it gets too complicated, something is probably
wrong.




More information about the redhat-list mailing list