Bash脚本:保持一行本地文件与远程文件同步

时间:2012-11-22 17:28:32

标签: linux bash ssh sync

我搜索过高和低,但似乎无法找到解决这个问题的方法(也许它不存在?)。这是我的问题:

我的本​​地计算机上有一个名为myFile.txt的文件。远程计算机上有一个名称相同的文件(myFile.txt)。两个文件结构都是这样的:

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

两个文件都具有完全相同的布局。我需要编写一个脚本,使两个文件(本地和远程)的<tag3>之间的字符串保持同步。我需要从远程服务器上的<tag3>获取字符串,并将其与本地计算机上的相同字符串进行比较。如果存在差异,我需要更改本地字符串以反映远程字符串。

到目前为止我尝试过的事情: 我使用awk抓取了本地字符串,并将其分配给变量。很容易。我ssh'ed到远程服务器并尝试使用相同的方法将远程字符串分配给变量。据我所知,这似乎有效。问题是变量没有返回我的本地机器有一个值(如果这是有道理的)。这就是我试图这样做的方式:

#!/bin/bash

fileName="myFile.txt"
logon="myUserName@remoteServer.com"


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  

当我回显$ remoteString时,我可以看到分配的变量。根据我的理解,这是在远程服务器上发生的,因为我正在将正确的字符串打印到控制台,然后是“未找到命令”。下一行echo是“remote string =”。所以$ x要么丢失它的值,要么从未正确分配。我已经尝试改变这一行,其中$ x被分配很多次,但没有任何运气。

其他想法: 如果这是不可能的,我开始认为我可能需要做一个文件的scp,把它带到我的服务器,进行比较,然后删除复制的文件。我需要在将副本移动到本地计算机之前更改副本的名称,否则我将覆盖我的文件。此外,不必制作安全副本似乎更有效,因为此脚本必须在许多计算机上运行,​​并且该文件可能比3行大很多。我已经研究了差异,但是找不到让它比较一条线的方法。

我对bash脚本很新,所以如果我遗漏了一些明显的东西,请原谅我。感谢您的帮助,非常感谢。

3 个答案:

答案 0 :(得分:1)

ssh命令存在一个转义问题 - 您应该转义$参数中的ssh

然后,我只用remoteString=$(awk ....); echo $remoteString替换了awk ....。如果没有,则存在一些导致空白行不匹配的问题 - 将命令的输出仅存储到echo似乎没用。

#!/bin/bash

fileName="myFile.txt"
logon="myUserName@remoteServer.com"


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

答案 1 :(得分:1)

您可以使用以下内容:

#!/bin/bash 
fileName="myFile.txt"
logon="myUserName@remoteServer.com"

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

(这似乎比你的方法简单)。 sed命令查找以<tag3>开头并以<tag3>开头的行的第一次出现,并删除标记以便仅传输“auth key”。没有防范不存在的文件,或者没有找到标签。这个细节留待读者阅读。但是脚本对于文件名中的空格是安全的,并且不使用两个嵌套的子shell!

答案 2 :(得分:0)

尝试更改此行:

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

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

即:将"<tag3>"更改为'<tag3>'

我觉得你目前使用的双引号实际上打破了ssh命令的预期用途。


作为旁注:当您单独[进行条件测试时,始终将变量用双引号括起来:

if [ $localString == $x ]; then

会更安全:

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

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

原因是如果任一变量求值为空字符串(假设在这种情况下x为空),bash会看到类似这样的内容:if [ ASDFA23RASDF29ASDJ29DJ2 == ]; then