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

时间:2014-05-30 18:47:13

标签: linux bash shell

我试图创建一个小脚本来检查备份驱动器是否正常以及它的磁盘使用情况详细信息,并将其作为活动检查服务器添加到nagios中。一旦我写了一个,我就会得到一些我无法纠正的未知错误。

脚本是:

#!/bin/sh

BACKUP_DRIVE='/backup'

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

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

        if [[ "$( df -h|grep backup|awk '{print $5}' | 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

错误是:

# 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

它在第一个if条件本身得到错误而没有进入内部if条件。

是否需要在提及变量$ BACKUP_DRIVE的位置进行更正?请帮助我,因为我是一个打击脚本的初学者。

2 个答案:

答案 0 :(得分:5)

立即问题 - 可能是触发语法错误的问题 - 是:

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

  • 使用#!/bin/bash代替shebang。
  • 使用可执行文件显式启动脚本时,请使用bash,而不是sh;在您的示例中:bash /usr/local/src/backupcheck.sh

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

  • 重写您的脚本以仅使用POSIX功能,在这种情况下,需要将[[ ... ]]替换为[ ... ](但在一般情况下通常需要更多更改)。

如果您确定sh实际上bash在您的系统上并且您不需要该脚本可移植(在其他平台上运行),则只能在不重写的情况下离开。


但是,您的条件还有问题:

看起来你的前两个条件只是为了测试所附的命令是否成功

通常,您根本不需要[[ ... ]]进行此类测试,而只是直接使用if命令,可能用!否定,并根据需要抑制输出>/dev/null2>/dev/null

因此,而不是你的命令:

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

你应该使用:

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

grep表示已找到(至少)与退出代码0匹配的内容,这也是if视角的成功。因此,实际上,如果备份驱动器存在,将执行if命令的正文。

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

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

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

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

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

最后:

  • 您应该通过stderr重定向echo命令,将错误消息输出到2>/dev/null;同样,您应该使用exit 1(或任何其他非零退出代码)在出现错误时退出,以便正确发出错误信号。
  • 正如@Charles Duffy在对OP的评论中指出的那样,有可能使你的命令更有效率。

答案 1 :(得分:1)

在某些时候,它正在尝试将$BACKUP_DRIVE参数作为数学表达式进行评估。试试这个:

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