Check for process and kill if running
Solution 1
Your syntax has many problems:
remove spaces around "=" when setting a variable
wrong:
APP_ID = value
right:
APP_ID=value
to run a program and put its output into a variable, you need
$(...)
(preferred in bash, not available in sh) or backticks`command`
(supported in bash and sh). (and remember that when assigning a variable, quotes are not needed, but in other cases they are important:command "$(command)"
)wrong:
APP_ID=command
right:
APP_ID=$(command)
add spaces around everything when using "[", and you need a semicolon or newline after the "]". This is because "[" is a bash builtin command, and the non-builtin one is also known as "test" (see
man test
), which just like other commands, takes its arguments separated by space:wrong:
if[x!= y] then echo hello world fi
right:
if [ x != y ]; then echo hello world; fi
use double quotes, not single quotes when you want to expand a variable
wrong:
if [ '' != '${APP_ID}' ]; then
right:
if [ '' != "${APP_ID}" ]; then
Also for the above example, you can use -n (non-empty) instead of comparing to empty string
if [ -n "${APP_ID}" ]; then
And for the ps example, you don't need grep and awk:
APP_ID=$(ps -C whoami --no-header --format 'pid')
And so here is the fixed up script:
APP_ID=$(ps -C whoami --no-header --format 'pid')
if [ -n "${APP_ID}" ]; then
echo "Stopping instance $APP_ID"
fi
Solution 2
This is easiest done with pgrep
and pkill
:
if pgrep process_name 2>/dev/null; then
echo "Terminating process_name"
pkill process_name
fi
As user @OrangeDog points out in the comments, there is the theoretical possibility of this shell code failing to terminate the process process_name
if the process spawns inbetween the call to pgrep
and pkill
. In this case, pgrep
would not detect the process and pkill
would never execute. How much of a problem this is, I don't know. If the process spawns just after the statement, what can you do?
Just do
echo "terminating process_name (if it is running)"
pkill process_name
to be rid of the pesky race condition in any case.
Solution 3
I am not sure why but the above script was not giving any syntax issues but was not giving the process id also though the process was running.
I finally changed it as below and it works -
APP_ID=$(ps -ef | grep <app_name> | grep java | awk '{print $2}')
echo "Instance $APP_ID"
if [ -n "${APP_ID}" ]; then
echo "Stopping instance $APP_ID"
fi
Thanks once again for the explanation and pointers.
@Peter I will check again the script you posted on why it is not working for me.
Related videos on Youtube
user179309
Updated on September 18, 2022Comments
-
user179309 over 1 year
I am trying to find if a process is running or not, and if it is runing then I want to call a script or print something. I tried with the below few ways, but it gives me syntax error or command not found error.
APP_ID = ps -eaf | grep -i `whoami` | grep -i <process_name> | grep -i java | awk '{print$2}' if[''!= '${APP_ID}'] then echo "Stopping instance $APP_ID"
I get the result as below:
test.sh: line 15: APP_ID: command not found test.sh: line 17: if[!= ${APP_ID}]: command not found Stopping instance
What is wrong in the above script? And if it has some errors, then why does it print the
echo
in theif
condition?Also the below script fails saying
test.sh: line 3: [ps: command not found
if [ps -eaf | grep -i `whoami` | grep -i <process_name> | grep -i java]; then echo 'stop' fi
-
ctrl-alt-delor almost 8 years
[
is a built in of bash. But behaves as if it is a separate command. On some shells it is. You can find[
in/usr/bin/[
, and it has a man page. -
user179309 almost 8 yearsThanks for the reply. Do we need to provide the pid in the above script ? I just have the process name which I want to stop. I am very new to scripting and trying to learn hence please bear with me for the stupid questions.
-
vipin almost 8 years@user179309 in the above script, it looks by name, just like you did with
whoami
, and the APP_ID will be a single or multi-line string including all the process ids (depending on how many processes are found). -
vipin almost 8 years@richard thanks, I guess you're right that I implied it's the same when it's not, so I fixed that.
-
OrangeDog almost 8 yearsWhy bother checking beforehand?
-
Kusalananda almost 8 years@OrangeDog Because in script in the question, the OP clearly tries to do the same.
-
OrangeDog almost 8 yearsThis has a race condition. The process you kill may not be the same one that you grepped for.
-
Kusalananda almost 8 years@OrangeDog There is technically a race condition in there in terms of what PIDs gets signalled, true. But the signal with be delivered to the instances of
process_name
running whilepkill
is executing none the less. It would have been worse if I had taken the PIDs frompgrep
and fed them tokill
, which might have left some recently spawned instance ofprocess_name
running. This will not be the case here. -
Kusalananda almost 8 years@OrangeDog The "worst" thing that could happen is that
process_name
terminates before we get topkill
. -
OrangeDog almost 8 yearsNo the worst thing that happens is you kill the replacement process for the one you were supposed to be killing.
-
Kusalananda almost 8 years@OrangeDog If I wanted to kill a specific process, I would not use
pkill
, I would keep track of the PID of that process and usekill $somepid
. In this case, I find it hard to come up with even an academic situation where this race condition would cause undesired results. Oh, there is one! Ifprocess_name
spawns inbetween the calls, without existing before. Sigh, I'll add a note.. -
Kusalananda almost 8 years@OrangeDog It's still just academic. If you run
pkill process_name
and the process spawns just afterwards, what have you gained? -
Gilles 'SO- stop being evil' almost 8 yearsDon't do this
ps … | grep …
stuff, it's unreliable: sooner or later you'll end up killing an unrealted process with a resembling name. Usepgrep
instead.