nycfdtd
nycfdtd

Reputation: 404

Bash script: keep one line of local file in sync with remote file

I have searched high and low, but cannot seem to find a solution to this problem (maybe it doesn't exist?). Here is my problem:

I have a file on my local machine called myFile.txt. There is a file on a remote machine with the same name (myFile.txt). Both file structures look like this:

<tag1>November 22, 2012<tag1>
<tag2>version5.8<tag2>
<tag3>ASDFA23RASDF29ASDJ29DJ2<tag3>

Both files have this exact same layout. I need to write a script keeps the string in between <tag3> in sync for the two files (local and remote). I need to get the string from <tag3> on the remote server and compare it to the same string on my local machine. If there is a difference I need to change my local string to reflect the remote one.

What I've tried thus far: I've grabbed the local string using awk, and assigned it to a variable. Easy enough. I ssh'ed into the remote server and attempted to use the same method to assign the remote string to a variable. As far as I can tell, this seems to be working. The issue is the variable doesn't come back to my local machine with a value (if that makes sense). This is how I'm attempting to do this:

#!/bin/bash

fileName="myFile.txt"
logon="[email protected]"


localString=$(awk -F "<tag3>" '{print $2}' $fileName)

x=$(ssh $logon "remoteString=$(awk -F "<tag3>" '{print $2}' $fileName); echo $remoteString")
echo "remote string = $x" 

if [ $localString == $x ]; then
echo "The 2 auth keys are EQUAL!!!"
else
echo "The 2 auth keys are NOT equal!!!"
fi  

I can see the variable being assigned when I echo out $remoteString. From my understanding this is happening on the remote server though as I'm getting the correct string printed to console followed by "command not found". The next line echo's "remote string = ". So $x is either losing it's value or is never properly assigned. I've tried varying this line where $x is assigned many many time, but have not had any luck.

Other ideas: If this isn't possible I'm beginning to think maybe I need to do a scp of the file, bring it over to my server, make the comparison, and then delete the copied filed. I would need to change the name of the copy before moving it to my local machine, or else I will overwrite my file. Also, it would seem more efficient not to have to make a secure copy because this script will have to run on many machines, and the file will potentially be a lot bigger than 3 lines. I've looked into diff, but can't find a way to get it to compare just one line.

I am fairly new to bash scripting so please forgive me if I am missing something obvious. Thank you for any help as it is greatly appreciated.

Upvotes: 3

Views: 1121

Answers (3)

gniourf_gniourf
gniourf_gniourf

Reputation: 46823

You can use something along these lines:

#!/bin/bash 
fileName="myFile.txt"
logon="[email protected]"

sedcommand='/^<tag3>.*<tag3>$/{s/<tag3>\(.*\)<tag3>/\1/p;q}'

localString=$( sed -n $sedcommand "$fileName" )
remoteString=$( ssh "$logon" "sed -n '$sedcommand' \"$fileName\"" )

if [[ $localString == $remoteString ]]; then
    echo "The 2 auth keys are EQUAL!!!"
else
    echo "The 2 auth keys are NOT equal!!!"
fi

(which seems simpler than your method). The sed command finds the first occurence of a line starting by <tag3> and ending by <tag3> and removes the tags so as to transfer only the "auth key". There's no guard against files that don't exist, or against the tag not being find. This detail is left to the reader. But the script is safe regarding spaces in file names and doesn't use two nested subshells!

Upvotes: 1

mgarciaisaia
mgarciaisaia

Reputation: 15560

There's a escaping issue with the ssh commands - you should escape the $ inside the ssh parameters.

Then, I just replaced the remoteString=$(awk ....); echo $remoteString with just awk ..... If not, there was some issue with a leading blank line that made the strings to not match - and it seems pretty useless to store a command's output just to echoing it.

#!/bin/bash

fileName="myFile.txt"
logon="[email protected]"


localString=$(awk -F "<tag3>" '{print $2}' $fileName)

x=$(ssh $logon "awk -F '<tag3>' '{print \$2}' $fileName")
echo "remote string = $x" 

if [ "$localString" == "$x" ]; then
        echo "The 2 auth keys are EQUAL!!!"
else
        echo "The 2 auth keys are NOT equal!!!"
fi

Upvotes: 1

sampson-chen
sampson-chen

Reputation: 47267

Try changing this line:

x=$(ssh $logon "remoteString=$(awk -F "<tag3>" '{print $2}' $fileName); echo $remoteString")

to

x=$(ssh $logon "remoteString=$(awk -F '<tag3>' '{print $2}' $fileName); echo $remoteString")

i.e.: change "<tag3>" to '<tag3>'

I have a feeling that your current use of the double quotes is actually breaking the intended use of your ssh command.


As a side note: always wrap your variables in double quotes when you single ['s for condition tests:

if [ $localString == $x ]; then

would be safer as:

if [ "$localString" == "$x" ]; then

or

# this also works, but less portable
if [[ $localString == $x ]]; then

The reason is that if either variable evaluates to the null string (suppose in this case x is empty), bash would see something like this instead: if [ ASDFA23RASDF29ASDJ29DJ2 == ]; then

Upvotes: 0

Related Questions