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

Jon*_*ndi 1 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
Run Code Online (Sandbox Code Playgroud)

错误是:

# 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
Run Code Online (Sandbox Code Playgroud)

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

在提到变量$ BACKUP_DRIVE时,是否需要进行任何修正?请帮助我,因为我是一个bash脚本的初学者.

mkl*_*nt0 5

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

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

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

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

  • 重写脚本,以使用POSIX才有的功能,这在当前情况下,需要更换[[ ... ]][ ... ](但在一般情况下,通常需要更多的变化).

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


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

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

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

因此,而不是您的命令:

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

你应该使用:

if grep $BACKUP_DRIVE /etc/fstab >/dev/null; then 
Run Code Online (Sandbox Code Playgroud)

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

请注意,我已经删除了awk命令,因为(a)是没有必要的测试和(b)实际上失败的,因为它会导致总的结果是测试0(成功),即使grep命令失败.

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

if df -h | grep $BACKUP_DRIVE >/dev/null; then
Run Code Online (Sandbox Code Playgroud)

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

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

最后:

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

  • 有两种选择:1.使用bash.2.不要使用bash.对于选项1,shebang需要是`#!/ bin/bash`,并且不应该将脚本调用为`sh script-name.sh`.对于选项2,脚本不应该使用`[[`...`]]`.任何一种选择都是完全有效的. (2认同)