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.