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

bash, linux, shell

Solution

The immediate issue - 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 (`[[ ... ]]`).

- Use `#!/bin/bash` as the shebang instead.

- When explicitly starting a script with an executable, use `bash`, not `sh`; in your example: `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`:

- 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).

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

However, there are also issues with your conditionals:

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

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/null` or `2>/dev/null`:

Thus, instead of your command:

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

you should use:

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

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

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

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:

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

Finally:

- You should output your error messages to `stderr` by redirecting the `echo` commands 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.

Problem

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. Script is: ``` #!/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 ``` 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. 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.

Original source