107

How can I determine if a process is running or not and then have a bash script execute some stuff based on that condition?

For example:

  • if process abc is running, do this

  • if it is not running, do that.

  • 1
    Feel it important to note that none of the solutions below take into account the state of the process. A comment on one of my questions brought me here, but an answer on it clued me into different state's of a program, like zombie process' (Not what I would describe as a "running" process). A full list of what the STAT column values, in the output of ps, indicates is here for those inclined to write an answer that accommodates this, or edit their own. – user66001 Oct 19 '13 at 17:54
  • Related discussion: unix.stackexchange.com/questions/74185/… – blong Jun 17 '14 at 17:08
  • best way to check for process exists: stackoverflow.com/questions/3043978/… – Trevor Boyd Smith Jun 7 '16 at 15:44

13 Answers 13

165
+50

A bash script to do something like that would look something like this:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

This script is just checking to see if the program "gedit" is running.

Or you can only check if the program is not running like this:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi
  • @DreadPirateShawn can you tell me why use /dev/null and not simply a 0? Using the number makes the code way more readable, at least for a noob (such as me). No redirect, no nothing – Silviu Nov 9 '15 at 18:46
  • 2
    @Silviu huh? Googling /dev/null: "/dev/null redirects the command standard output to the null device, which is a special device which discards the information written to it" ... using 0 would redirect the command output to a file called 0. In this case, I'd advise becoming more comfortable with > /dev/null -- you'll see it everywhere, as it's the standard / proper way to discard output. – DreadPirateShawn Nov 10 '15 at 5:33
  • Woot thanks, I used this for a nice little script that checks if a program is running before it executes. (although I had to extend it a little since google chrome's executable doesn't have the same name as it's run command, the exec name is just chrome.) – Cestarian Jan 31 '16 at 18:22
  • 3
    Please add the -x parameter to pgrep so that it is looking for the exact application or else it will get a false correct if it finds the same string inside the name of another app. I just spent 1 hour to find that out. – Thanos Apostolou Aug 31 '16 at 21:24
  • 1
    To check if the program is not running use ! pgrep – Mohammed Noureldin Jan 21 '17 at 22:29
34

Any solution that uses something like ps aux | grep abc or pgrep abc are flawed.

Why?

Because you are not checking if a specific process is running, you are checking if there are any processes running that happens to match abc. Any user can easily create and run an executable named abc (or that contains abc somewhere in its name or arguments), causing a false positive for your test. There are various options you can apply to ps, grep and pgrep to narrow the search, but you still won't get a reliable test.

So how do I reliably test for a certain running process?

That depends on what you need the test for.

I want to ensure that service abc is running, and if not, start it

This is what init and upstart are for. They'll start the service and ensure its pid gets stored in a pidfile. Try to start the service again (via init or upstart) and it will check the pidfile, and either start it if it's not there, or abort if it's already running. This is still not 100% reliable, but it's as close as you get.

See How can I check to see if my game server is still running... for other solutions.

abc is my script. I need to make sure only one instance of my script is running.

In this case, use a lockfile or a lockdir. E.g.

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

See Bash FAQ 45 for other ways of locking.

  • 3
    While this is technically true, I've ne er personally encountered such a problem in real life. Most programs don't change their names in ways that break scripts. Thus, for simple scripts something like pgrep or ps is perfectly adequate and your approach seems like overkill. If you're writing a scrip for public distribution, though, you should write it in the safest way possible. – Scott Severance Jun 30 '12 at 13:21
  • 2
    @ScottSeverance Programs changing names is not the issue; that would require intervention regardless. It's other users running the same program, or other programs with similar names that will suddenly cause the script to get false positives and thus do the wrong thing. I just prefer "works" rather than "mostly works". – geirha Jun 30 '12 at 14:15
  • 2
    I misspoke. But many of us run single-user systems. And in a multiple user situation, it's easy to also grep for the username. – Scott Severance Jun 30 '12 at 21:03
  • 1
    what if your script fails during runtime and dies prior to unlocking the file? – jp093121 Aug 14 '14 at 17:41
  • 2
    @jp093121 The EXIT trap is triggered when the script exits. Whether it exits because it reaches end of script, an exit command, or receives a signal (that can be handled), the rm command is run. So as long as it ends after the trap has been set, the lock should be gone. – geirha Aug 16 '14 at 18:30
18

This is what I use:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

In plain English: if 'pgrep' returns 0, the process is running, otherwise it is not.


Related reading:

Bash Scripting :: String Comparisons

Ubuntu Manuals pgrep

  • thanx! i tried this too n it works perfectly too :) – Nirmik Jun 29 '12 at 23:10
  • pgrep has the same 15 character limit "feature" previously mentioned, thus for example pgrep gnome-power-manager would also fail – Thorsen Jul 2 '12 at 16:04
  • 1
    Make sure you use pgrep's -x option: "Only match processes whose name (or command line if -f is specified) exactly match the pattern." – Alastair Irvine Jul 21 '14 at 4:31
5

I usually have a pidof -x $(basename $0) on my scripts to check if it's already running.

2

Riffing on @rommel-cid's idea, you can use pidof with the || (||) to run a command if the process does not exist and && to run something if the process does exist, thus creating a quick if/then/else conditional. For example here's one with a running process (my chrome browser, whose process name is "chrome") and one testing for a process that does not exist. I suppressed the standard output using 1>/dev/null so that it doesn't print:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$
1

None of the "simple" solutions worked for me because the binary I need to check is not installed system-wide, so I have to check with path, which in turn requires using ps -ef | grep approach:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi
0

First thing that came to my mind for your problem:
ps aux | grep -i abc will show the details of the process if its running. You may match the number of lines or time for which its running and compare with zero or any other manipulation. When you run the above command it will show you atleast one line of output i.e. detail about the process created by thi grep command.. So take care of that.
That should do as a simple hack. Put it in the bash script and see if its helpful.

0

Using start-stop-daemon:

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

It works as normal user.

0

I found that the accepted answer posted by @John Vrbanac did not work for me, and that the answer posted by @geirha doesn't answer the original question.

John Vrbanac's solution didn't work to check if a PHP process was running or not for me, I'm running CentOS 7.

@geirha's answer only makes sure an instance isn't already running before starting another. This was not the original question, the original question was to check if a process is running or not.

Here's what worked for me:

Say my process had the string "Jane" in it's process name. This will find if it's running or not. This works for BASH and PHP scripts.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi
  • 1
    Ah, well as this is an Ubuntu Q&A site it's not surprising that some of the answers here don't work on CentOS 7 as that Linux is off-topic here. Other versions of Linux are supported at unix.stackexchange.com – Elder Geek Nov 11 '16 at 19:17
  • although the author of the answer uses CentOS, this answer still is valid for ubuntu. – Phillip -Zyan K Lee- Stockmann Nov 11 '16 at 19:34
0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

Note: pgrep -x lxpanel or pidof lxpanel still reports that lxpanel is running even when it is defunct (zombie); so to get alive-and-running process, we need to use ps and grep

-1

As of 23 September 2016, pgrep appears to require an option "-x" in order for muru's script to work.

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

I tried and tested the above script on an Ubuntu 16.04.1 machine. Enjoy!

-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid=`pgrep -x ${1}`  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done
  • 1
    Welcome to Ask Ubuntu! I recommend editing this answer to expand it with specific details about what this does. (See also How do I write a good answer? for general advice about what sorts of answers are considered most valuable on AskUbuntu.) – David Foerster Jan 28 '17 at 19:02
-3

isProcessRunning() { if [ $(pidof $1) > /dev/null ]; then retval='true'; else retval='false'; fi; echo $retval; }

isProcessRunning geany

true

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.