Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
 |
06-03-2005, 11:33 AM
|
#1
|
Member
Registered: Mar 2005
Location: London, United Kingdom
Distribution: Fedora Core 5
Posts: 83
Rep:
|
Bash: Check if a program is running
Hello All,
I'm using Xorg 6.8.2 and the new composite extension. The visual effects are great, however it is still buggy.
One of the things that happen is that when I click (in GNOME) on Log Out, X crashes.
I've had to get around the problem by killing Xcompmgr (the composite manager) just before I log off. This gets tedious, having to do it every time I log out.
So I decided to make a custom application launcher, which runs a shell script when clicked on.
What I want the shell script to do is check if the program is already running or not, before it does anything. Basically, it'll act as a switch -- if xcompmgr is running, it'll kill it, and if it isn't running, it'll start it. What I need to know is how to get the script to check whether it's running or not.
The test command in bash scripting can only test certain things, most of them file based.
Here's my script as it stands:
Code:
#!bin/bash
if [ <my test goes here -- needs to return a true value if the process is running> ]
then killall xcompmgr
else exec xcompmgr -c -f
fi
Thanks for your time.
|
|
|
06-03-2005, 12:43 PM
|
#2
|
Moderator
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417
|
many ways, e.g.
Code:
if [ "$(pidof process_name)" ]
then
# process was found
else
# process not found
fi
Last edited by acid_kewpie; 06-03-2005 at 12:45 PM.
|
|
|
06-04-2005, 03:30 AM
|
#3
|
Member
Registered: Mar 2005
Location: London, United Kingdom
Distribution: Fedora Core 5
Posts: 83
Original Poster
Rep:
|
Thank you very much, that was exactly what I was looking for!
|
|
|
09-20-2009, 09:10 AM
|
#4
|
LQ Newbie
Registered: Sep 2009
Posts: 1
Rep:
|
How to check if another instance of same script is running
Just to add my 5 cents to this discussion, if you want to check whether another instance of the same script is running you might want to try this:
Code:
if pidof -x $(basename $0) > /dev/null; then
for p in $(pidof -x $(basename $0)); do
if [ $p -ne $$ ]; then
echo "Script $0 is already running: exiting"
exit
fi
done
fi
|
|
1 members found this post helpful.
|
02-13-2010, 08:22 PM
|
#5
|
LQ Newbie
Registered: Feb 2010
Posts: 1
Rep:
|
I'm not sure what the difference is between pidof and pgrep, but I use the latter.
Code:
if [ -z "$(pgrep foo)" ]
then
# foo is not running
else
# foo is running
fi
Last edited by Gimlic; 02-13-2010 at 08:25 PM.
|
|
|
12-24-2011, 04:48 PM
|
#6
|
LQ Newbie
Registered: Dec 2011
Posts: 1
Rep: 
|
The difference I see between pidof and pgrep is:
1-) pgrep greps the given process name where as pidof exactly matches the process name. ie pidof may not find processes name /bin/bash but pgrep will find all processes containing bash key.
2-) pidof separator is blank space while pgrep separator is newline.
|
|
|
12-27-2011, 05:36 AM
|
#7
|
Member
Registered: Jan 2009
Location: New England
Distribution: Arch Linux
Posts: 719
Rep: 
|
If you just want to kill the system....
Code:
#! /bin/bash/
shutdown -h now .... Goodbye $USER
exit 0
|
|
|
05-04-2012, 04:38 AM
|
#8
|
LQ Newbie
Registered: May 2012
Location: USA
Posts: 3
Rep: 
|
also
Hi guys...
I would like to use a script like the one in this thread for checking on whether a process is running or not.
My situation is a tiny bit more complex.
I have a file generated that holds all the pids that I want to monitor.
How can I check on all these process`s to check whether one goes down or not? using the script in this thread??
anyone have any ideas?
Darren
|
|
|
05-04-2012, 12:49 PM
|
#9
|
Member
Registered: Jan 2009
Location: New England
Distribution: Arch Linux
Posts: 719
Rep: 
|
Not tested...
Code:
#! /bin/bash
check_it ()
{
wc -l file w/ PID > List
sleep 10
wc -l file w/ PID >Check
if [[ $(wc -l Check) -lt $(wc -l List) ]]
then
echo "Process Ended"
else
echo "No Issue"
fi
}
while [1] then check_it
exit
|
|
|
05-08-2012, 07:14 AM
|
#10
|
LQ Newbie
Registered: May 2012
Location: USA
Posts: 3
Rep: 
|
Quote:
Originally Posted by jv2112
Not tested...
Code:
#! /bin/bash
check_it ()
{
wc -l file w/ PID > List
sleep 10
wc -l file w/ PID >Check
if [[ $(wc -l Check) -lt $(wc -l List) ]]
then
echo "Process Ended"
else
echo "No Issue"
fi
}
while [1] then check_it
exit
|
Hmmm it does bum out on the 'while' saying not matched...
I take it there`s no differences with korn shell?
also this is my understanding wc -l <pathtofile> > List?
Darren
|
|
|
05-08-2012, 08:28 AM
|
#11
|
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
|
If you have a list of process IDs in file pidlist, first read it into a variable. For illustration, I'll use sed to edit out any non-PIDs, and read them into a space-separated string.
Code:
PIDS="$(sed -ne 's|^[\t\v\f ]*\([0-9]\+\)[\t\v\f ]*$|\1|p' pidlist | tr -s '[[:space:][:cntrl:]]' ' ')"
You might wish to use [ -n "$PIDS" ] at this point to verify there is at least one PID in PIDS.
Next, use ps to list the PIDs of still existing processes. Try to do it using a single command, because the ps command overhead is quite large. Only calling it once will be significantly faster than calling it for each PID separately.
Code:
ALIVE=" $(ps -o pid= -p "${PIDS[*]}" | tr -s '[[:space:][:cntrl:]]' ' ') "
Note that this one will have a space before and after every PID, including at the start and end of the string. This way, in Bash, you can use [ "$ALIVE" != "${ALIVE/ $PID /}" ] to test if PID is listed in ALIVE.
The only thing left to do is to check which PIDs from PIDS are listed in ALIVE.
Code:
for PID in $PIDS ; do
if [ "$ALIVE" != "${ALIVE/ $PID /}" ]; then
echo "Process $PID is still alive."
else
echo "Process $PID has died."
fi
done
If you just want arrays of the PIDs that are still running or have died, you can rewrite the loop as
Code:
RUNNING=()
DIED=()
for PID in $PIDS ; do
if [ "$ALIVE" != "${ALIVE/ $PID /}" ]; then
RUNNING[${#RUNNING[@]}]=$PID
else
DIED[${#DIED[@]}]=$PID
fi
done
# There are ${#RUNNING[@]} processes still running: ${RUNNING[@]}
# ${#DIED[@]} of the processes are gone: ${DIED[@]}
There is however a serious flaw in the overall logic, that should be fixed:
Because PIDs are reused eventually, the new PID could be a totally unrelated process!
To counter that, if all the processes run the same command, you could use
Code:
ALIVE=" $(ps -o pid= -C command | tr -s '[[:space:][:cntrl:]]' ' ') "
instead. This one lists all the PIDs for processes whose executable name is command. Or, if there are a few different names, use -C "cmd1 cmd2 .. cmdN" instead.
This way only existing processes running that command or those commands are considered.
There are other approaches, too. A typical one is to check that the still alive processes are in the right session or process group. I'd personally pick the approach depending on exactly what the processes are running, and how they are related. For typical servers, checking the executable name or process group is common, and those you can do by adjusting the parameters to the ALIVE ps command; instead of limiting to the set of PIDs in PIDS, look for all acceptable processes, and let the loop handle the limiting to the original set. See the man 1 ps manpage for details.
Last edited by Nominal Animal; 05-08-2012 at 08:31 AM.
|
|
|
05-08-2012, 10:48 AM
|
#12
|
LQ Newbie
Registered: May 2012
Location: USA
Posts: 3
Rep: 
|
Hi...
thanks so much for replying...
I`m fairly new to scripting...so I`m still trying to digest half of this
but I`m getting an error
ps: 0509-048 Flag -p was used with invalid list.
I`m guessing in korn shell it doesn`t like the p flag with the commands I`ve passed to it..
also this list of pids is static all through the day and it changes the following day.. so I can schedule this script to run during trading hours, stop and then run again the following day.. shouldn`t be a problem I think..
Darren
Quote:
Originally Posted by Nominal Animal
If you have a list of process IDs in file pidlist, first read it into a variable. For illustration, I'll use sed to edit out any non-PIDs, and read them into a space-separated string.
Code:
PIDS="$(sed -ne 's|^[\t\v\f ]*\([0-9]\+\)[\t\v\f ]*$|\1|p' pidlist | tr -s '[[:space:][:cntrl:]]' ' ')"
You might wish to use [ -n "$PIDS" ] at this point to verify there is at least one PID in PIDS.
Next, use ps to list the PIDs of still existing processes. Try to do it using a single command, because the ps command overhead is quite large. Only calling it once will be significantly faster than calling it for each PID separately.
Code:
ALIVE=" $(ps -o pid= -p "${PIDS[*]}" | tr -s '[[:space:][:cntrl:]]' ' ') "
Note that this one will have a space before and after every PID, including at the start and end of the string. This way, in Bash, you can use [ "$ALIVE" != "${ALIVE/ $PID /}" ] to test if PID is listed in ALIVE.
The only thing left to do is to check which PIDs from PIDS are listed in ALIVE.
Code:
for PID in $PIDS ; do
if [ "$ALIVE" != "${ALIVE/ $PID /}" ]; then
echo "Process $PID is still alive."
else
echo "Process $PID has died."
fi
done
If you just want arrays of the PIDs that are still running or have died, you can rewrite the loop as
Code:
RUNNING=()
DIED=()
for PID in $PIDS ; do
if [ "$ALIVE" != "${ALIVE/ $PID /}" ]; then
RUNNING[${#RUNNING[@]}]=$PID
else
DIED[${#DIED[@]}]=$PID
fi
done
# There are ${#RUNNING[@]} processes still running: ${RUNNING[@]}
# ${#DIED[@]} of the processes are gone: ${DIED[@]}
There is however a serious flaw in the overall logic, that should be fixed:
Because PIDs are reused eventually, the new PID could be a totally unrelated process!
To counter that, if all the processes run the same command, you could use
Code:
ALIVE=" $(ps -o pid= -C command | tr -s '[[:space:][:cntrl:]]' ' ') "
instead. This one lists all the PIDs for processes whose executable name is command. Or, if there are a few different names, use -C "cmd1 cmd2 .. cmdN" instead.
This way only existing processes running that command or those commands are considered.
There are other approaches, too. A typical one is to check that the still alive processes are in the right session or process group. I'd personally pick the approach depending on exactly what the processes are running, and how they are related. For typical servers, checking the executable name or process group is common, and those you can do by adjusting the parameters to the ALIVE ps command; instead of limiting to the set of PIDs in PIDS, look for all acceptable processes, and let the loop handle the limiting to the original set. See the man 1 ps manpage for details.
|
|
|
|
05-08-2012, 10:24 PM
|
#13
|
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
|
Quote:
Originally Posted by Stainy
ps: 0509-048 Flag -p was used with invalid list.
|
Are you running on AIX?
Try comma-separated lists:
Code:
PIDS="`tr -cd '0-9\r\n' < pidfile | tr -s '[\n\r ]' ','`"
PIDS="${PIDS//,,/,}"
PIDS="${PIDS##,}"
PIDS="${PIDS%%,}"
# If you know the executables, use
ALIVE=",`ps -o pid= -C 'cmd1,cmd2,...,cmdN' | tr -s '[\t\n\v\f\r ]' ','`,"
# otherwise, use
ALIVE=",`ps -o pid= -p $PIDS | tr -s '[\t\n\v\f\r ]' ','`,"
for PID in ${PIDS//,/ } ; do
if [ "$ALIVE" != "${ALIVE/,$PID,/}" ]; then
echo "$PID still running"
else
echo "$PID has exited"
fi
done
Note that if you set IFS="," then the for loop is written for PID in $PIDS ; do .
|
|
|
All times are GMT -5. The time now is 11:04 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|