You said you incorporated it, not copied it letter-for-letter...
Could you put echo statements inside the loops to see where it's hanging?
#!/usr/bin/sh
while read fname; do
bname=$(basename $fname)
echo "trying "${fname} (${bname})" >&2
first=0
{
echo "running hostname" >&2
hostname
echo "finished running hostname, now running /usr/local/bin/hosts" >&2
/usr/local/bin/hosts
} | while read box; do
echo "ssh-ing to box ${box}" >&2
t=$(ssh ${box} "/usr/local/bin/md5 /opt/dba/scp/$bname" | awk '{print $4}')
if [ $first -eq 0 ]; then
hash=$t
first=1
else
[ "${hash}" = "${t}" ] || echo "Files are not Identical!!!"
fi
done
done < /home/izivanov/iz3
Also fixed some might-have-been-syntax errors, highlighted in red. Not all shells know what == means, but = should go. And you shouldn't have loose !'s hanging around unquoted, in some shells ! is a history command.
this || that means "run this, and if it fails, run that". So if it's not equal, it runs echo ...
The && syntax is the opposite: run this, if it succeeds, run that.
It's very handy for chaining a number of dependent commands in a row without needing n+1 levels of nested if. a && b && c && d && e will stop at b if b fails.
My bad, I put an extra quotation mark in that. Substitute this line:
(root):/home/izivanov# sh dirsync3.sh
trying /opt/dba/scp/xxxxxxxx (xxxxxxxxxxxc)
running hostname
ssh-ing to box xxxxxxx
finished running hostname, now running /usr/local/bin/hosts
trying /opt/dba/scp/xxxxxxxxx (xxxxxxxxxx)
running hostname
ssh-ing to box xxxxxxxx
finished running hostname, now running /usr/local/bin/hosts
trying /opt/dba/scp/xxxxxxxxxxx (xxxxxxx)
running hostname
ssh-ing to box xxxxxx
finished running hostname, now running /usr/local/bin/hosts
trying /opt/dba/scp/xxxxxxxxxx (xxxxxxxxxxxx)
running hostname
ssh-ing to box xxxxxx
finished running hostname, now running /usr/local/bin/hosts
trying /etc/sudoers (sudoers)
running hostname
ssh-ing to box xxxxxxx
finished running hostname, now running /usr/local/bin/hosts
trying /opt/dba/binxxxxxxxxxx (xxxxxxxxxxxx)
running hostname
ssh-ing to box xxxxxxx
finished running hostname, now running /usr/local/bin/hosts
At least that's output! Confused on the output. It doesn't give me much useful info about which box these files are not identical to the original box...
---------- Post updated at 02:31 PM ---------- Previous update was at 02:25 PM ----------
Looks like its just running the hosts and hostname and not recognizing them as executables!
---------- Post updated at 02:33 PM ---------- Previous update was at 02:31 PM ----------
Somehow its supposed to run the MD5 on the file against the "hosts" file and also "hostname" which is the current box name from which I'm running this script!
You were running these files as executables before -- maybe accidentally, but that had me assuming they were scripts. Are they actually just text files?
Well, if it's printing "ssh-ing to box rtidsva", it must be pulling that name from somewhere, so I think it really is executing those two programs and reading the names appropriately.
I assume this 'first' variable is to compare all following with the local host. Why not do that separately to avoid confusion and cut a big chunk of extra logic out?
#!/usr/bin/sh
while read fname; do
bname=$(basename $fname)
echo "trying "${fname} (${bname})" >&2
hash=$(/usr/local/bin/md5 /opt/dba/scp/$bname | awk '{print $4}')
echo "local hash is ${hash}"
/usr/local/bin/hosts | while read box ; do
echo "ssh-ing to box ${box}" >&2
t=$(ssh ${box} "/usr/local/bin/md5 /opt/dba/scp/$bname" | awk '{print $4}')
echo "comparing ${hash} to ${t}" >&2
[ "${hash}" = "${t}" ] || echo "Files are not Identical!!!"
done
done < /home/izivanov/iz3
(root):/home/izivanov# sh dirsync5.sh
trying /opt/dba/scp/xxxxxxxxx (xxxxxxxxc)
local hash is xxxxxxxxxxxxxxxxxx
ssh-ing to box box2
comparing xxxxxxxxxxxxxxxxxxxxx to xxxxxxxxxxxxxxxxxxxxxxxx
~
~
~
~
Check what /usr/local/bin/hosts prints. That loop won't break until read fails for some reason. Try running /usr/local/bin/hosts by itself and see what it does.
You can't md5sum things like /etc/sudoers without root access. And automatic passwordless remote root access to every machine is scary, so maybe you don't want to check that one... That weird 'opened' must be part of an error message -- odd place for it to end up, I'd have expected them to go to stderr!
But we're getting there. It's definitely able to verify some files now.
Btw I am running with root access. I didn't need to provide my login info to ssh with the script before to do this check either.
Its executable from anywhere with just "hosts" line. If I run it from Box 1 from which we make all our changes from, I get a list of all the boxes:
box 1(root):/home/izivanov# hosts
box 2
box 3
box4
~
~
~
box n
And if I run it from box 2, I'll get:
box 1
box3
box4
~
~
~
Box n
Do you understand?
So running the script from box 1, its getting only the first line of `hosts`, i.e. Box 2, and then not checking the file in question against that box either!
We also include `hostname' executable so that it would do this check on every box including the one I'm currently on, box 1! But it's not doing that!
I really don't understand why it's not looping through all hosts... When loops break down like that, simplify it until you get something that works as expected and build from there.
while read fname; do
bname=$(basename $fname)
echo "trying "${fname} (${bname})" >&2
hash=$(/usr/local/bin/md5 /opt/dba/scp/$bname | awk '{print $4}')
echo "local hash is ${hash}"
# should just print the entire list of hosts repeatedly
/usr/local/bin/hosts
done < /home/izivanov/iz3
It displayed the local hash, and then listed all of the servers. However I don't even need the see the hash. I just need to display on which server the hash doesn't correspond to the original file hash!
---------- Post updated at 12:35 PM ---------- Previous update was at 12:32 PM ----------
Sorry here is the output also:
(root):/home/izivanov# sh dirsync6.sh
trying /opt/dba/scp/xxxxxxxxxxx (xxxxxxx)
local hash is xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Box 2
box 3
etc
and then it repeats for all the files the same!
Lol, I guess I am trained now to spot errors and remember them. You keep putting the " in
echo "trying "${fname} (${bname})" >&2
But now I notice it! Anyway, yeah here it is:
A couple of cannot open things on the bottom. Not really sure what that is!
---------- Post updated at 12:54 PM ---------- Previous update was at 12:50 PM ----------
Also what should I re-name the variable t with. My boss said that its not best practice to do that cause if anyone else looks at the script they won't know what the t stands for! I'm not sure what it stands for either! I know that it compares the hash-es of the files!
---------- Post updated at 12:55 PM ---------- Previous update was at 12:54 PM ----------
right, I was about to ask you about what to do if the files are different. My sync report got changed!
It's because not all your files are under /opt/dba/scp/. Check your list file and tell me, which ones should be converted from (whatever)/filename into /opt/dba/scp/filename, and which ones should be left as-is?
Or can they all be left as-is? In that case:
while read fname; do
#bname=$(basename $fname)
echo "trying ${fname}" >&2
hash=$(/usr/local/bin/md5 "$bname" | awk '{print $4}')
echo "local hash is ${hash}" >&2
# should just print the md5's
/usr/local/bin/hosts | while read box
do
T=$(ssh ${box} "/usr/local/bin/md5" "$fname" | awk '{ print $4;}')
[ "$T" = "$hash" ] || echo "${box} $fname differs!"
done
done < /home/izivanov/iz3
As for the syntax errors, ordinarily i'd try shell code I post on my own system before offering it to you but that's impossible for this script...
I'd be more interested in the contents of /home/izivanov/iz3 actually...
I spotted an error in my script. I left a bname in when inappropriate.
And one really should check the return value of md5 here. It bizzarely spews its errors to stdout, so whenever something goes wrong, the loop checks garbage vs garbage and decides everything's OK.
# If you don't have mktemp, TMP=/tmp/$$ will do. mktemp is more secure.
TMP=`mktemp`
while read fname; do
#bname=$(basename $fname)
echo "trying ${fname}" >&2
if ! /usr/local/bin/md5 "$fname" > "$TMP"
then
echo "md5 on ${bname} failed: "
# print the error
cat "$TMP"
continue
fi
hash=$(awk '{print $4}' "$TMP")
echo "local hash is ${hash}" >&2
# should just print the md5's
/usr/local/bin/hosts | while read box
do
T=$(ssh ${box} "/usr/local/bin/md5" "$fname" | awk '{ print $4;}')
[ "$T" = "$hash" ] || echo "${box} $fname differs!"
done
done < /home/izivanov/iz3
# clean up temp file
rm -f "$TMP"