-1

I have a script sh startAWS.sh. On top of it, i checked this :

if [[ `ps -acx|grep postgres|wc -l` < 1 ]]; then
    echo "You need to start your Postgres service to run this script."

    ps -acx|grep postgres|wc -l

    exit 0
fi

When I run , I got

⚡️  laravel  sh startAWS.sh                                                            
You need to start your Postgres service to run this script.                           
       6  

Hmm... what... ‍♂️

My Postgres is running, that echo should not be executed.

It shows 6, and 6 is not less than 1, that code should not be executed.

Does anyone know why I echo is printing out?

cyb3rZ
  • 43,853
  • 82
  • 251
  • 430

2 Answers2

1

You need to perform a numeric comparison so use -lt or -gt in your check.

Comparing numbers in Bash

if [[ `ps -acx|grep postgres|wc -l` -lt 1 ]];
wooknight
  • 114
  • 7
1

There are a couple of problems here.

First, as @RameshNaidu pointed out, inside [[ < ]] is doing string comparison (i.e. alphabetical order) rather than numeric, and that's causing trouble. The usual problem this mistake causes is that string sorting order is different than numeric order -- for instance, [[ 10 < 2 ]] evaluates to true, because "1" comes before "2" in character sorting order. But that doesn't apply here, because "6" comes after "1" in sorting order as well. What's happening is subtler than that: wc -l prints a number of spaces before the number of lines, and space does come before "1", so [[ " 6" < 1 ]] evaluates to true.

Second, ps | grep something is a bad way to check whether a process is running, because (depending on the exact timing) the ps command may include "grep something" in its output, and the grep command will match that. If you have pgrep available, use that instead, since it automatically avoids this problem. Another common workaround is to use grep "[s]omething" instead -- the brackets prevent it from matching itself, so you don't get this extra match.

But there's also a much simpler way to see if there were any matches: rather than using wc to count matches, just use grep -q (or pgrep -q) to suppress output, and just check its exit status (success = found at least one match, so negate it with ! to check for no match). It'll look like one of these:

if ! pgrep -q postgres; then
    echo "You need to start your Postgres service to run this script."

or

if ! ps -acx |grep -q "[p]ostgres"; then
    echo "You need to start your Postgres service to run this script."
Gordon Davisson
  • 95,980
  • 14
  • 99
  • 125