相关文章推荐
打篮球的甘蔗  ·  Use getaddrinfo to ...·  2 月前    · 
坐怀不乱的领带  ·  c++ ...·  7 月前    · 
深情的馒头  ·  用Excel ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm writing this script, which should detect an error after the smart test is done. But I can't get it to detect any error, or not of course.

 if [[ smartctl --log=selftest /dev/sda | awk 'NR>7 {print $4,$5,$6,$7}' | sed 's/offline//g; s/00%//g' != *"Completed without error"* ]; then
 echo "No error detected"
 else echo "Error detected"

Output:

./test.sh: line 19: conditional binary operator expected
./test.sh: line 19: syntax error near `--log=selftest'
./test.sh: line 19: `if [[ smartctl --log=selftest /dev/sda | awk 'NR>7 {print $4,$5,$6,$7}' | sed  's/offline//g; s/00%//g' != *"Completed without error"* ]]; then'

So obviously I'm doing something wrong. But all the tutorials say two [[]] thingies, but I think the command is quite complex, it doesn't work... How can I make it work?

[[ ]] is a specific command, not part of general-purpose if syntax. If you don't want to run that command, don't put it in your syntax. – Charles Duffy Jan 31, 2017 at 18:28 Rather, you need to capture the string output by the pipeline in order to compare it to the given pattern. – chepner Jan 31, 2017 at 18:28 Removing the [[ ]] I get sed: can't read !=: No such file or directory sed: can't read *Completed without error*: No such file or directory – Florius Jan 31, 2017 at 18:30 Yes, the != calls for [[ ]]. Suffice to say that this was a long and hairy enough command that it looked like a different common error at first glance. – Charles Duffy Jan 31, 2017 at 18:31

If you want to do a substring comparison, you need to pass a string on the left-hand side of the = or != operator to [[ ]].

A command substitution, $(), will replace the command it contains with its output, giving you a single string which can be compared in this way.

That is:

smartctl_output=$(smartctl --log=selftest /dev/sda | awk 'NR>7 {print $4,$5,$6,$7}' | sed 's/offline//g; s/00%//g')
if [[ "$smartctl_output" != *"Completed without error"* ]; then
   : ...put your error handling here...

or, a bit less readably:

if [[ "$(smartctl --log=selftest /dev/sda | awk 'NR>7 {print $4,$5,$6,$7}' | sed 's/offline//g; s/00%//g')" != *"Completed without error"* ]; then
   : ...put your error handling here...
                Okay, that works, kind off.. I'm not sure with what the if error compares though... It says error detected although there are none. Is there something wrong with the != *"Completed without error"* comparison?  [root@operations ~]# ./test.sh Error detected [root@operations ~]# smartctl --log=selftest /dev/sda | awk 'NR>7 {print $4,$5,$6,$7}' | sed  's/offline//g; s/00%//g'  Completed without error  Completed without error
– Florius
                Jan 31, 2017 at 18:47
                Okay, got it. I actually didn't think of making it a variable, I was thinking too complex! Thank you for giving me another look on it!
– Florius
                Jan 31, 2017 at 18:52

You are confusing things. If the command you want to test is smartctl, don't replace it with [[. You want either or, not both. (See also e.g. Bash if statement syntax error)

Anyway, piping awk through sed and then using the shell to compare the result to another string seems like an extremely roundabout way of doing things. The way to communicate with if is to return a non-zero exit code for error.

if smartctl --log=selftest /dev/sda |
   awk 'NR>7 { if ($4 OFS $5 OFS $6 OFS $7 ~ /Completed without error/) e=1; exit }
       END { exit 1-e }'
     echo "No error detected"
     echo "Error detected"
                Your command will always exit 1, though you have exit 0 before END block, for example run this echo 1 | awk '{exit 0}END{exit 1}'; echo $?
– Akshay Hegde
                Jan 31, 2017 at 18:37
                You can do something like this to correct, awk 'BEGIN{e=1}NR>7 { if ($4 OFS $5 OFS $6 OFS $7 ~ /Completed without error/) e=0} END { exit e&&1 }'
– Akshay Hegde
                Jan 31, 2017 at 18:46
                That works! Got one question, if the output gives for example error on Disk /dev/sda, will it still says no error detected because it reads the word "error"? Or does it only compare to the complete /Completed without error/ string?
– Florius
                Jan 31, 2017 at 18:51
                @Florius, /Completed without error/ will only match that exact string (absent the delimiters) in full.
– Charles Duffy
                Jan 31, 2017 at 21:02
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.