Check if service is running prior to install using Puppet - bash

I need to check if a service is already running before it installed using puppet.
My code is as following, but it is keep failing.
exec { 'bud_sh':
cwd => '/working_dir/',
command => "Some Command",
path => '/usr/bin:/usr/sbin:/bin:/usr/local/bin',
provider => 'shell',
onlyif => "test -f /path/to/shell/script/exist",
unless => "`ps -eaf | grep service | grep -v grep | wc -l` -eq 3"
}
Following is the Error Message.
Could not evaluate: /bin/sh: 3: command not found
Appreciate your time and consideration on this matter.

This error message ...
Could not evaluate: /bin/sh: 3: command not found
indicates that the shell tried to execute '3' as a command, and, unsurprisingly, did not find it. The only plausible source of such an issue in the code you presented is your Exec's unless command:
unless => "`ps -eaf | grep service | grep -v grep | wc -l` -eq 3"
When the command there is executed by the shell, it first executes
ps -eaf | grep service | grep -v grep | wc -l
in a subshell and captures its standard output. That output is slightly cleaned up, and then substituted into the overall command to yield, apparently,
3 -eq 3
, which the shell then tries to execute as the command '3', with two arguments. To instead evaluate that as a conditional expression, you need to present it as arguments to test or [ or similar:
unless => "test `ps -eaf | grep service | grep -v grep | wc -l` -eq 3"

unless => "ps -eaf | grep service | grep -v grep | wc -l -eq 3"
Other issues aside, you have a syntax error: -eq 3 is not a valid command. If you want to evaluate the output of a shell command in sh, you need to use a test construct. For example:
unless => '[ "$(ps -eaf | grep service | grep -v grep | wc -l)" -eq 3 ]'
On a broader level, the unless statement is looking for a truthy Boolean value. The test construct does that by providing its exit status. Write your statements with that in mind.

Related

ps pipe and grep shell scripting illegal argument

New to shell scripting and just writing a little script to check if a process is running, if I use
PROCESS_NUM="ps -ef | grep '$1' | grep -v 'grep' | wc -l"
I get a "ps: illegal argument: |" error although if I echo out PROCESS_NUM and ctrl paste in the line it works just fine manually. Not sure why the | pipe is being troublesome here. Any help is much appreciated!
If you are trying to assig the output of ps -ef | grep '$1' | grep -v 'grep' | wc -l command to PROCESS_NUM variable, you need to use below:
PROCESS_NUM=`ps -ef | grep '$1' | grep -v 'grep' | wc -l`
or
PROCESS_NUM=$(ps -ef | grep '$1' | grep -v 'grep' | wc -l)
Using "", will treat the value inside of it as a string, except for some special character

Bash script: argument not found

I have a small bash script (check_status) by which I am trying to know if a process is running or not.
#!/bin/bash
# check argument
if ["$1" == ""];
then
echo "Invalid argument"
exit 3
fi
PN=$(ps -ef | grep $1 | wc -l)
echo "process is $1: executing $PN"
if [ $PN -gt 1 ];
then
status=OK
message=UP
exit=0
else
status=CRITICAL
message=DOWN
exit=2
fi
echo "$status - $1 is $message"
exit $exit
However, when I run this from shell sh checkstatus xyz I get this:
check_status: 3: check_status: [xyz: not found
process is xyz: executing 3
OK - xyz is UP
Now, my first problem is the check_status: 3: check_status: [xyz: not found error. I dont know why its showing up.
Next,there is no process xyz running in my server. So, as per my understanding I am running ps -ef | grep xyz | wc -l in the shell which should echo 1 if no process is running. But, I am getting 3.
How do I fix this?
Update
I changed if ["$1" == ""]; to if [ "$1" = "" ] Now I am not getting the error. But still my PN=$(ps -ef | grep $1 | wc -l) is returning 3.
I then updated PN=$(ps -ef | grep $1 | wc -l) to PN=$(ps -ef | grep $1 ) which gave me the following response:
admin 14674 4570 0 12:03 pts/2 00:00:00 sh check_status xyz
admin 14675 14674 0 12:03 pts/2 00:00:00 sh check_status xyz
admin 14677 14675 0 12:03 pts/2 00:00:00 grep xyz
One sh check_status xyz and one grep xyz makes seance to me. But, any idea why I see two of them ?
(1) As mentioned elsewhere, you'll need spaces around "[" and "]".
(2) If your ps supports the -c option, you should consider using it. Otherwise, if you use ps, you will need to parse the output in some way. (You might want to insert "| tee /dev/tty" to see what your ps command is producing.) But is grep (or pgrep) really what you want here? The messages your script is producing suggest otherwise.
(3) If, for example, you want an exact match of the basename, consider the following (which is broken down into separate steps so you can more easily adapt it to your purpose):
ps -c | awk '{print $4}' | grep "^$x\$"
Other than the spaces around [ that others have mentioned, you should change this:
PN=$(ps -ef | grep $1 | wc -l)
to this:
PN=$(pidof $1 | wc -w)
That will get you a count of running processes that match the name you specified.
The reason you're getting a greater count than expected from your original code is because the grep command also adds one to the count, and it will also produce a hit on any other process that might happen to contain the same characters in its name as the process being targeted. Using pidof eliminates both of these factors.

Something is wrong with unix script

Following is my script, every time I run this it goes into else part. when I run the TEST2EVAL command it gives me 1
#!/bin/sh
TEST2EVAL='ps auxf | grep some.jar | grep -v grep | wc -l'
if [ "$TEST2EVAL" = 1 ]
then
java -jar /path/to/jar &
else
echo "Running"
fi
Assuming you are trying to find out if any processes are running with some.jar on their command lines you probably want:
if pgrep -f some.jar; then
echo running;
else
echo not running;
fi
In in order save the output of a command in a variable, you have to enclose the command in backticks (`), not single quotes ('). Thus, change the second line of your script to:
TEST2EVAL=`ps auxf | grep some.jar | grep -v grep | wc -l`
You are using the wrong quotes for command substitution: not single quotes:
TEST2EVAL='ps auxf | grep some.jar | grep -v grep | wc -l'
but backquotes:
TEST2EVAL=`ps auxf | grep some.jar | grep -v grep | wc -l`
Better yet, use TEST2EVAL=$(ps auxf | grep some.jar | grep -v grep | wc -l) instead. It's much clearer, supported by all POSIX-compatible shells, and can be nested more easily when necessary.

bash script inside here document not behaving as expected

Here is a minimal test case which fails
#!/bin/tcsh
#here is some code in tcsh I did not write which spawns many processes.
#let us pretend that it spawns 100 instances of stupid_test which the user kills
#manually after an indeterminate period
/bin/bash <<EOF
#!/bin/bash
while true
do
if [[ `ps -e | grep stupid_test | wc -l` -gt 0 ]]
then
echo 'test program is still running'
echo `ps -e | grep stupid_test | wc -l`
sleep 10
else
break
fi
done
EOF
echo 'test program finished'
The stupid_test program is consists of
#!/bin/bash
while true; do sleep 10; done
The intended behavior is to run until stupid_test is killed (in this case manually by the user), and then terminate within the next ten seconds. The observed behavior is that the script does not terminate, and evaluates ps -e | grep stupid_test | wc -l == 1 even after the program has been killed (and it no longer shows up under ps)
If the bash script is run directly, rather than in a here document, the intended behavior is recovered.
I feel like I am doing something very stupidly wrong, I am not the most experienced shell hacker at all. Why is it doing this?
Usually when you try to grep the name of a process, you get an extra matching line for grep itself, for example:
$ ps xa | grep something
57386 s002 S+ 0:00.01 grep something
So even when there is no matching process, you will get one matching line. You can fix that by adding a grep -v grep in the pipeline:
ps -e | grep stupid_test | grep -v grep | wc -l
As tripleee suggested, an even better fix is writing the grep like this:
ps -e | grep [s]tupid_test
The meaning of the pattern is exactly the same, but this way it won't match grep itself anymore, because the string "grep [s]tupid_test" doesn't match the regular expression /[s]tupid_test/.
Btw I would rewrite your script like this, cleaner:
/bin/bash <<EOF
while :; do
s=$(ps -e | grep [s]tupid_test)
test "$s" || break
echo test program is still running
echo "$s"
sleep 10
done
EOF
Or a more lazy but perhaps sufficient variant (hinted by bryn):
/bin/bash <<EOF
while ps -e | grep [s]tupid_test
do
echo test program is still running
sleep 10
done
EOF

Shell script to kill a process

I need to implement a shell script that kills a process. The problem is that I need to do a conditional to be able to see if the process is running or not.
This is my code, but it is not working:
#!/bin/sh
if [ -x "MY_PROCCESS_NAME"]; then
killall MY_PROCCESS_NAME
else
echo "Doesn't exist"
fi
This is the error:
line 3: [: missing `]'
to check if a process is running on mac os x you can use:
pid=$(ps -fe | grep 'process name' | grep -v grep | awk '{print $2}')
if you want to reduce the number of shell scripts you can enclose one of the characters of the name of the process in square brackets:
pid=$(ps -fe | grep '[p]rocess name' | awk '{print $2}')
combined in your test this would look like:
pid=$(ps -fe | grep '[p]rocess name' | awk '{print $2}')
if [[ -n $pid ]]; then
kill $pid
else
echo "Does not exist"
fi
it's a little more complicated than you would need to do under linux as you generally have the 'pgrep' command, which is the rough equivalent of the 'ps -fe | grep ... | grep -v grep'
not sure if it would work in OSX, it works in ubuntu.
but as a one liner:
ps aux | awk '$11~/vim/ {PID = $2} END {if (PID) print "kill -9 "PID; else print "echo no process"}' | bash
what it does is it finds a process, in this case, vim and returns the kill -9 pid if no string is found it returns echo no process it then pipes the output to bash.

Resources