0

I am able to run count command but when I use it in while condition, it is giving error:

-bash: [/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86-64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l: No such file or directory.


count="/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86- 
64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l"
while [ "$count" -ne 0 ]
do
echo "killing services and tomcat process"
/usr/bin/ps -aef|/usr/bin/egrep "catalina|java|wrapper-linux-x86- 
64"|/usr/bin/grep -v "catalina|java"|/usr/bin/awk '{print 
$2}'|/usr/bin/xargs kill -9
sleep 10
count="/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86- 
64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l"

done;
  • 1
    See pgrep -fc 'catalina|java|wrapper-linux-x86-64' to count the number of processes with those strings in their arg list. – Stéphane Chazelas Oct 3 '18 at 16:46
  • 1
    Use shellcheck.net to spot and help fix syntax errors – roaima Oct 3 '18 at 17:43
3
count="/usr/bin/ps -aef|...|wc -l"

Don't store commands in variables, they're not made for that and using the stored command is difficult. If you want to store the command somewhere, use a function instead:

count_procs() {
    /usr/bin/ps -aef|...|wc -l
}

A function can be used like any other command.

The code you've shown will compare the value of that string in count against zero as an integer. Bash's [ would complain about a non-numeric value.

The error you presented would come from a command like ["$count" -eq 0 ] (without a space between [ and $count), since in that case, the contents of count are concatenated with [ to form the first word of the command line, the name of the command to run. While it would be silly to do so, it's entirely possible to have a path that contains brackets, pipe characters and white space.

Now, assuming that you want to actually run the command and capture its output to compare against zero, you'll need to use command substitution $(...):

result=$(ps ... |wc -l)            # save the output of the command to `result`

or

[ "$(ps ... | wc -l)" -eq 0 ] ... # use the command output directly in a test

Assuming you want to count the processes every time the loop runs, you'll have to run the command within the loop body. So, e.g.

while [ "$(ps ... | wc -l)" -eq 0 ]; do
    ...
done

or, with a function

count_procs() {
    /usr/bin/ps -aef|...|wc -l
}
while [ "$(count_procs)" -eq 0 ]; do
    ...
done  

Just counting the processes once before the loop would make the condition a constant, and the loop would repeat indefinitely, or not at all.

2

In your while loop, you need to decrement your count variable.

count=10
while [ $count -ne 0 ]; do
    echo "Count is $count"
    ((count--))
done

For the actual arithmetic, there are a number of ways to do it, such as:

  • ((count--))
  • ((count-=1))
  • ((count=count-1))
  • count=$((count - 1))

For more info on double parentheses constructs, see: https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/dblparens.html

You could also use let:

  • let "count--"
  • let "count-=1"
  • let "count=count-1"

For more info on let, see: http://wiki.bash-hackers.org/commands/builtin/let


Edit: A note on POSIX compliant shells that don't have the same fancy features as bash.

Posix shells can use the $(( <expression> )) syntax. So if you had the same loop above, and you wanted to ensure it would work on a shell like ksh, or officially portable shell like CAE Issue 4 (XPG4)'s sh:

  • count=$((count - 1))

Using this syntax will make your script more portable than using bash specific syntax, if that matters to you.

  • Thanks for pointing that out, @Vlastimil, that's a good idea. Since bash is mentioned in the question, that's how the answer was written. But I'll add a note about arithmetic in POSIX shells. – Tim Kennedy Oct 3 '18 at 16:42
1

In addition to the confusion about command substitution quoting, the error message indicates you actually have while ["$count" -ne 0] without the required space around the brackets. Keep in mind that the the part after "while" is actually a command, and the loop ends when the command exits with a non-zero status (ref https://www.gnu.org/software/bash/manual/bashref.html#Looping-Constructs).

Due to the missing space, bash sees

while ["/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86-64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l" -ne 0]

and it is trying to execute the command ["/usr/bin/ps -aef|...|wc -l" which is obviously not found

It is important to remember that [ is actually a command and therefore a space after it is required to separate the command name from its first argument. (same reason you write ls -l and not ls-l). Also the [ command requires that ] is its last argument, so ] also needs whitespace separation.

At a bash prompt, type help [ and help test (and also help [[)

1

Simpler:

while pkill -f 'catalina|java|wrapper-linux-x86-64'; do 
  sleep 10
done

Still unsafe to kill processes based on their arg list.

0

Your main problem being usage of double quotes where there shall be:

$(...)

I have a few remarks to this part (too long for a comment):

while [ "$count" -ne 0 ]
do
echo "killing services and tomcat process"
done;

  • There is no stopping mechanism for the while loop like:

    count=$(( count - 1 ))
    
  • From a styling point, you should space the inner part.

  • Just to note, you don't need a semicolon at the end.

  • i am killing processes so count number would decrease, that part of code i didnt include in my question – RAJ METRE Oct 3 '18 at 13:24
-1

replace

count="..."

with

count=`...`
  • 1
    Please avoid this construct in favor for $(...). – LinuxSecurityFreak Oct 3 '18 at 12:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.