Redhat Shell脚本如果语句失败,出现奇怪的语法错误

Redhat 5.3 Enterprise

以下Shell脚本用于检查备份目录是否被命名为“ll_backup”,然后将其更改为等于文件RESULT.VAR的内容。 result.var文件被复制用于日志目的到另一个目录。 我在testing环境中工作,但是在制作过程中,它经历了一个奇怪的错误,我不能在我的生活中弄明白!

脚本:

#!/bin/bash #!/bin/cat # Restores original directory name for next LogLogic Update #TCJ 6/1/09 declare RESULT declare FILE FILE=result.var cd /home/nb-backup/backups/nb-st3000/ll_bkup_65.99.220.172/ if [ -d ll_bkup ] then cat result.var | while IFS=: read RESULT mv "ll_bkup" "$RESULT" mv result.var /home/storegrid/scripts/results/result-`date +%y%m%d%s`.var else exit 0 fi exit 0 

结果:

nb-script-restorellbackup.sh:第14行:语法错误附近意外的令牌else' nb-script-restorellbackup.sh: line 14: else'

有一些问题,从轻微到致命(所有致命的问题都与“猫……而……读”行有关)。 让我按顺序经过他们:

  • 正如Dennis Williamson所指出的,“#!/ bin / cat”和“declare …”这两行没有任何作用。
  • 您将FILE设置为靠近顶部的result.var,但不要使用此variables。 假设它只是为了让你在一个地方改变文件名,你应该用“$ FILE”replace所有其他对result.var的引用。
  • while语句需要一个“do … done” – 或者说,如果你真的需要while语句的话。 由于您只是从文件中读取一个RESULT,所以不需要循环。
  • 由于“读取结果”是pipe道的一部分,因此它运行在一个子shell中,并且当该子shell退出时,它所设置的RESULT的值将会丢失。 你可以通过使用像'read RESULT <“$ FILE”'这样的东西来解决这个问题。
  • 什么是“IFS =:”位呢? 它将内部字段分隔符设置为“:”在读取命令的持续时间,但由于您只读取一个字段(RESULT),所做的唯一操作是从result.var中读取的内容修剪前导或尾随冒号。 如果你打算忽略冒号后面的所有内容(即只使用result.var中的第一个冒号分隔字段),则应该使用“IFS =:read RESULT IGNOREDJUNK”。
  • 除非实际上试图修剪/parsingresult.var的内容,或者需要多次使用它,否则根本不需要将其读入variables; 只需使用“mv”ll_bkup“”$(cat“$ FILE”)“'。 但我声称你想再次使用它(见下文)。
  • 该脚本相当脆弱,因为它不检查以确保result.var存在(并且由于脚本移动该文件,如果连续运行两次,则保证第二次失败)。 同样,在尝试重新命名ll_bkup之前,它不检查“$ RESULT”是否已经存在,导致潜在的不可预知的结果。
  • 说到这一点,你的描述说result.var被复制,但实际的代码移动它。 哪个是预期的行为?
  • 最后,“else … exit 0”部分没有做任何事情,最后的“exit 0”不会做任何事情。

抱怨,抱怨,抱怨…无论如何,这里是我的build议重写:

 #!/bin/bash # Restores original directory name for next LogLogic Update #TCJ 6/1/09 FILE=result.var cd /home/nb-backup/backups/nb-st3000/ll_bkup_65.99.220.172/ if [ -d ll_bkup -a -f "$FILE" ]; then read RESULT <"$FILE" if [ ! -e "$RESULT" ]; then mv "ll_bkup" "$RESULT" mv "$FILE" /home/storegrid/scripts/results/result-`date +%y%m%d%s`.var fi fi exit 0 

while循环是怎么回事? 它需要do ... done某处。

这里给你一些参考资料:

  • Bash指南初学者
  • 高级Bash脚本指南

您需要将该行更改为如下所示:

 cat result.var | while IFS=:; do read RESULT; done 

这个catread在我看来,它设置$ RESULT等于文件“result.var”内容的最后一行的第一个单词

并删除这一行:

 #!/bin/cat 

因为它没有做任何事情。

在这种情况下你并不需要使用declare

在你的date命令周围使用$() 。 如果需要的话,它更具可读性,可以更容易嵌套。