Redhat Shell 脚本 If 语句因奇怪的语法错误而失败

Redhat Shell 脚本 If 语句因奇怪的语法错误而失败

Redhat 5.3 企业版

以下 Shell 脚本用于检查备份目录是否名为“ll_backup”,然后将其更改为等于文件 RESULT.VAR 的内容。result.var 文件被复制到另一个目录以用于日志记录。我在测试环境中运行了此脚本,但在生产中它出现了一个奇怪的错误,我无论如何也想不通!

脚本:

#!/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附近有语法错误

答案1

存在许多问题,从轻微问题到严重问题不等(所有严重问题都与“cat...while...read”行有关)。让我按顺序介绍一下:

  • 正如丹尼斯·威廉姆森 (Dennis Williamson) 指出的那样,“#!/bin/cat”和“declare...”行没有任何作用。
  • 您在顶部附近将 FILE 设置为 result.var,但从未使用过此变量。假设它旨在允许您仅在一个地方更改文件名,则应将对 result.var 的所有其他引用替换为“$FILE”
  • while 语句需要“do...done”——或者说,如果您确实需要 while 语句的话,它确实需要。由于您只从文件中读取一个 RESULT,因此不需要循环。
  • 由于“读取 RESULT”是管道的一部分,因此它在子 shell 中运行,并且当该子 shell 退出时,它设置的 RESULT 值将丢失。您可以使用类似“读取 RESULT <"$FILE"”的命令来修复此问题。
  • 那里的“IFS=:”位是做什么用的?它在读取命令的持续时间内将内部字段分隔符设置为“:”,但由于您只读取一个字段(RESULT),因此它所做的唯一事情就是从 result.var 读取的内容中修剪前导或尾随冒号。如果您想忽略冒号后的所有内容(即仅使用 result.var 中第一个以冒号分隔的字段),则应改用“IFS=: read RESULT IGNOREDJUNK”。
  • 除非您实际上试图修剪/解析 result.var 的内容,或者需要多次使用它,否则您根本不需要将其读入变量;只需使用“mv "ll_bkup" "$(cat "$FILE")"”。但我声称您想再次使用它(见下文)。
  • 该脚本相当脆弱,因为它不会检查以确保 result.var 存在(并且由于脚本移动了该文件,如果连续运行两次,则第二次肯定会失败);同样,它在尝试将 ll_bkup 重命名为“$RESULT”之前不会检查它是否已经存在,从而可能导致不可预测的结果。
  • 说到这,您的描述说 result.var 被复制了,但实际代码移动了它。哪个是预期的行为?
  • 最后,“else...exit 0”部分不会执行任何操作,而最后的“exit 0”无论如何也不会执行任何操作。

抱怨,抱怨,抱怨...无论如何,这是我建议的重写:

#!/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

答案2

while 循环发生了什么?它需要do ... done某个地方。

以下是一些供您参考的资料:

答案3

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

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

在我cat看来read,它将 $RESULT 设置为等于文件“result.var”内容最后一行的第一个字

并删除此行:

#!/bin/cat

因为它什么也没做。

declare在这种情况下您确实不需要使用。

在日期命令周围使用$()。这样更易读,必要时还可以更轻松地嵌套。

相关内容