Bash 脚本错误:“语法错误:预期操作数(错误标记为“/backup”)”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23961463/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:35:00  来源:igfitidea点击:

Bash Script error: "syntax error: operand expected (error token is "/backup")"

linuxbashshell

提问by JohnW

I was trying to make a small script to check if backup drive is fine and its disk usage details, and to add it to nagios as an active check in servers. Once I written one, I got some unknown errors that I don't to correct.

我试图制作一个小脚本来检查备份驱动器是否正常及其磁盘使用详细信息,并将其添加到 nagios 作为服务器的主动检查。一旦我写了一个,我就遇到了一些我不想纠正的未知错误。

Script is:

脚本是:

#!/bin/sh

BACKUP_DRIVE='/backup'

if [[ "$( grep $BACKUP_DRIVE /etc/fstab | awk '{print }')" -ne "0" ]]; then 

    if [[ "$( df -h | grep $BACKUP_DRIVE | awk '{print }')" -ne "0" ]]; then

        if [[ "$( df -h|grep backup|awk '{print }' | cut -d "%" -f1)" -ge "95" ]]; then
            echo "CRITICAL: Backup Drive usage exceeded 95%"
        fi
    else
        echo "CRITICAL: Backup Drive not mounted"
    fi
else
    echo "CRITICAL: Backup Drive not added in fstab"
fi

Error is:

错误是:

# sh /usr/local/src/backupcheck.sh
/usr/local/src/backupcheck.sh: line 6: [[: /backup: syntax error: operand expected (error token is "/backup")
CRITICAL: Backup Drive not added in fstab

It's getting error at the first if condition itself and not getting into the inner if conditions.

它在第一个 if 条件本身出现错误,而不是进入内部 if 条件。

Is there any corrections need to be done at point where variable $BACKUP_DRIVE mentioned? Please help as I am a beginner to bash scripting.

在提到变量 $BACKUP_DRIVE 的地方是否需要进行任何更正?请帮助,因为我是 bash 脚本的初学者。

回答by mklement0

The immediateissue- likely the one triggering the syntax error - is:

直接的问题-可能是一个触发语法错误-是:

You're using shebang #!/bin/sh, which is NOT guaranteed to be bash(and even if it is, it behaves differently), yet you're using bash-specific syntax ([[ ... ]]).

您正在使用 shebang #!/bin/sh,这不能保证bash(即使是,它的行为也不同),但您使用的是特定于 bash 的语法 ( [[ ... ]])。

  • Use #!/bin/bashas the shebang instead.
  • When explicitly starting a script with an executable, use bash, not sh; in your example: bash /usr/local/src/backupcheck.sh
  • 使用#!/bin/bash的家当来代替。
  • 当使用可执行文件显式启动脚本时,请使用bash,而不是sh; 在你的例子中:bash /usr/local/src/backupcheck.sh

Alternatively, with the shebang as is and if you want to be able to invoke your script explicitly with sh:

或者,按原样使用shebang,如果您希望能够使用sh以下命令显式调用您的脚本:

  • Rewrite your script to use POSIX features only, which in the case at hand requires replacing [[ ... ]]with [ ... ](but in the general case typically requires more changes).
  • 重写您的脚本以仅使用 POSIX 功能,在手头的情况下需要替换[[ ... ]][ ... ](但在一般情况下通常需要更多更改)。

You can only get away without rewriting if you know for sure that shis actually bashon your system and you do not need the script to be portable (run on other platforms).

如果您确定这sh确实bash在您的系统上并且您不需要脚本是可移植的(在其他平台上运行),那么您只能在不重写的情况下逃脱。



However, there are also issues with your conditionals:

但是,您的条件也存在问题

It looks like your first 2 conditionals are meant to only test whether the enclosed command succeedsor not.

看起来您的前 2 个条件仅用于测试所包含的命令是否成功

Generally, you do not need [[ ... ]]for such tests at all, and instead simply use the command directly with if, possibly negated with !, and with output suppressed as needed with >/dev/nullor 2>/dev/null:

通常,您根本不需要[[ ... ]]这样的测试,而只需直接使用命令 with if,可能否定 with !,并根据需要使用>/dev/nullor抑制输出2>/dev/null

Thus, instead of your command:

因此,而不是您的命令:

if [[ "$( grep $BACKUP_DRIVE /etc/fstab | awk '{print }')" -ne "0" ]]; then 

you should use:

你应该使用:

if grep $BACKUP_DRIVE /etc/fstab >/dev/null; then 

grepwill indicate having found (at least) a match with exit code 0, which is (also) success from if's perspective. Thus, effectively, the ifcommand's body will be executed if the backup drive exists.

grep将表明已找到(至少)与退出代码匹配,0if的角度来看,这(也是)成功。因此,有效地,if如果备份驱动器存在,命令的主体将被执行。

Note that I've removed the awkcommand, as it (a) isn't necessary for the test and (b) actually defeatsthe test in that it will cause the overall result to be 0(success), even if the grepcommand failed.

请注意,我已经删除了awkcommand,因为它 (a) 不是测试所必需的,并且 (b) 实际上会使测试失败,因为0即使grep命令失败,它也会导致整体结果为(成功)。

Similarly, your 2nd conditional should read:

同样,您的第二个条件应为:

if df -h | grep $BACKUP_DRIVE >/dev/null; then

Finally, your 3rd conditional is correct in principle: it captures stdout output from the pipeline and compares it to a percentage number (though double-quoting the number is not necessary and potentially confusing). However, you accidentally hard-coded the drive name, so instead it should be:

最后,您的第三个条件原则上是正确:它从管道中捕获 stdout 输出并将其与百分比数字进行比较(尽管双引号数字不是必需的并且可能会造成混淆)。但是,您不小心硬编码了驱动器名称,因此它应该是:

if [[ "$(df -h | grep $BACKUP_DRIVE | awk '{print }' | cut -d "%" -f1)" -ge 95 ]]; then


Finally:

最后:

  • You should output your error messages to stderrby redirecting the echocommands with 2>/dev/null; similarly, you should use exit 1(or any other nonzero exit code) to exit in case of error, so as to properly signal an error condition.
  • As @Charles Duffy points out in comments on the OP, there is potential for making your commands more efficient.
  • 您应该stderr通过重定向echo命令来输出错误消息2>/dev/null;同样,您应该使用exit 1(或任何其他非零退出代码)在出现错误时退出,以便正确地发出错误信号。
  • 正如@Charles Duffy 在对 OP 的评论中指出的那样,有可能使您的命令更高效。

回答by Tripp Kinetics

At some point, it's trying to evaluate the $BACKUP_DRIVEparameter as a math expression. Try this instead:

在某些时候,它试图将$BACKUP_DRIVE参数计算为数学表达式。试试这个:

grep $BACKUP_DRIVE /etc/fstab | awk '{print }'
if [[ $? -ne 0 ]] ; then
...