First of all, I'd reduce that war-crime of an awk/grep/awk/grep/awk/grep/etc statement down to:
df | awk '$5~/([7-9]|10)[0-9]/'
It does everything you need to check output. You could add a {print ...}
clause to the awk
statement if you really needed pretty output but given that you're just checking to see if there is output, let's be reasonable about this ☺.
We can also shorten the if/else. I've also corrected the direction — yours was reversed. The whole command now looks like:
[[ -n $(df | awk '$5~/([7-9]|10)[0-9]/') ]] && echo 'ACHTUNG!' || echo 'No >=70s'
I think you'd agree that's just slightly more edifying.
Now you could probably escape this manually now and wrap it in a bash -c "..."
but where's the fun in that? Instead let's save the command into a local file (say commands.txt) you can send that to the server like so:
ssh user@host $(<commands.txt)
And you could leave it there. You could actually throw a working version of your original command in there and send that over. This thing is pretty robust... But we don't want to do that... Not when we can be more clever (and cheaty) with the command and do away with the if brackets (which are the things causing the escaping problem).
We are currently running df
remotely and processing it remotely. We don't need to do that. We could let ssh
just run df
and then handle the output locally. That instantly nixes the escaping problem but we're currently tied up in logic [[
brackets ]]
which would make the rewrite a bit ugly:
[[ -n $(ssh user@host df | awk '$5~/([7-9]|10)[0-9]/') ]] && .......
Yuck.
We are better than that.
Unlike the monkeys and apes who trod before us, we have exit codes.
When something finishes running, it can return a code. These codes mean various things but generally speaking 0
means "I did exactly what I was designed to do" and anything higher means "I did bad, Bawss".
Conditional hooks like &&
and ||
look to the exit code feeding into them to decide whether or not to run. In our case this means if we tell awk
to exit in a non-zero way, we can control the code flow:
ssh user@host df | awk '$5~/([7-9]|10)[0-9]/ {exit 1}' && echo 'No >=70s' || echo 'ACHTUNG!'
This also means that it will exit as soon as it detects the first >=70 value. If you had millions of drives, that could save you seconds over other leading-brand scripts. So yes, just to reaffirm what's going on in this final version:
- We are connecting to the server and running
df
remotely
- The output is piped back to a local instance of
awk
awk
looks to see if the fifth column matches a regex to match 70-100
- If it does, it exits code 1 and the
||
code executes (there is a drive over 70% used)
- If it doesn't, it exits code 0 and the
&&
code executes.
In previous revisions I also had a NR>1
check in the awk
statements but given we're explicitly checking the value of the fifth column (and it has the be a number to work), we can safely omit that too.