1

Sorry for possible spam, I'm finishing RHEL Security Hardening/Auditing script, where I want an overall result in the end. For example,

# PermitEmptyPasswords
grep -E '^\s*PermitEmptyPasswords\s+no\s*' /etc/ssh/sshd_config &> /dev/null
if [ $? = 0 ];
then echo "[ OK ] PermitEmptyPasswords is properly configured";
else echo "[ ERROR ] PermitEmptyPasswords is not properly configured";
fi

Now, my idea for overall result (Safe/Not safe) is to make sum of all these if $? cases, if all cases give sum of 0, it will echo "This system is properly configured by hardening policy", else echo "This system has errors" + reprint all errors where $? is > 0.

How to get this work? I'm new at scripting, so any help will be appreciable. Thanks in advance.

5
  • What's the problem? Do you have an error message? Commented Aug 8, 2017 at 11:46
  • I don't have any error messages. I need an example how to sum all if [ $? = 0 ]; cases from all of my modules and print a message when the sum of all if [ $? = 0 ]; are 0, and another message for any > 0 Commented Aug 8, 2017 at 11:50
  • @Kristian: $? is generated for every shell command run and bash does not store the history of exit codes of all the previous commands, just the last command's value is known in $?. Explain your requirement more, I am sure there is a better way to do what you are trying to achieve here Commented Aug 8, 2017 at 11:51
  • pics.rs/i/M64xQ - on this screenshot I've put some explanation. To simplify it, all OK's > in the end I must have a message "All marks are OK", if there's a single error in one of the sections, another message in the end will be shown: Fix errors: 1/3/5 etc. Commented Aug 8, 2017 at 11:58
  • Personally, btw, rather than a sum I tend to use a bitmask in similar cases. foo; (( retval |= $? )) ORs the bits of $? from command foo in with what you already have in the variable retval. Commented Aug 8, 2017 at 17:21

2 Answers 2

3

@py9 has already answered the question, but I'd like to point something else out: when testing whether a command succeeded, it's simpler and somewhat more robust to use the command directly as the if condition, rather than using $? to check its exit status afterward. Also, rather than redirecting grep's output to /dev/null, you can use grep -q (quiet mode). Finally (as @CharlesDuffy pointed out), grep -E understands extended regular expression syntax, which doesn't include \s (that's part of PCRE -- perl-compatible regular expression -- syntax). So use something like this:

if grep -q -E '^[[:space:]]*PermitEmptyPasswords[[:space:]]+no[[:space:]]*' /etc/ssh/sshd_config; then
    echo "[ OK ] PermitEmptyPasswords is properly configured"
else
    echo "[ ERROR ] PermitEmptyPasswords is not properly configured"
    ((count++))
fi
Sign up to request clarification or add additional context in comments.

2 Comments

grep -E doesn't guarantee support of \s, which is not ERE but PCRE. Consider [[:space:]] instead. Otherwise, though, this is an important and well-made point.
@CharlesDuffy Good catch; I didn't even look at the RE. Fixed now.
2

What you can do is:

create an empty variable and give it a value of 0

count=0

Increment it by 1 every time you have an exit status bigger than 0. Example:

if [[ $? -gt 0 ]]; then ((count++)); fi

To print it all out at the end, you can do a simple array, but I think just appending the content to a file, and then reading at the end should suffice.

if [[ $? -gt 0 ]]; then ((count++)) && echo "whatever" >>filename; fi

At the end, just cat the filename and to show to the number of errors, just echo the count variable:

echo "Count number: $count"

P.S use double opening and closing brackets if you are using bash as your shell.

5 Comments

Does it work for if [ $? = 0 ]; also or it must be [[ $? - gt 0 ]]; because I don't understand really what -gt 0 variable does.
for comparing integers, it is not recommended to use "==". -gt 0 in this case means: Greater than 0.
If you're going to use bashisms, might make it (( $? > 0 )). That said, it's generally better to branch directly on your command's exit status where possible. foo || ((++count)) will do the job much more tersely with no $? in sight.
And note ++count vs count++ -- that difference can be important if folks use set -e; see the exercises in BashFAQ #105.
Users should prefer Gordon Davisson answer over this structure. Test the command directly--not its exit code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.