LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
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


Reply
  Search this Thread
Old 04-11-2012, 10:46 AM   #1
jlacroix
Member
 
Registered: Nov 2003
Posts: 187

Rep: Reputation: 15
Quick Help With Bash Script


I have the following script, which seems to work. Basically, what it does is run a command if a particular process is NOT running.

What I'd like to do is find out how to tailor this syntax to run as long as any of several processes aren't running, not just one as it is now.

Code:
#!/bin/bash
# init

if [ ! "$(pidof process_name)" ]
then
        echo "I'm doing it."
else
        echo "I'm not doing it."
fi
 
Old 04-11-2012, 10:55 AM   #2
MensaWater
LQ Guru
 
Registered: May 2005
Location: Atlanta Georgia USA
Distribution: Redhat (RHEL), CentOS, Fedora, CoreOS, Debian, FreeBSD, HP-UX, Solaris, SCO
Posts: 7,831
Blog Entries: 15

Rep: Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669
Code:
#!/bin/bash
# init

while true
do if [ ! "$(pidof process_name)" ]
   then
        echo "I'm doing it."
   else
        echo "I'm not doing it."
   fi
sleep 300
done
The while loop say to keep doing something until a condition is no longer valid. Using the keyword "true" means it is always valid so it will do it forever. You want to put a sleep as a governor. Mine is 300 seconds (5 minutes). You can lower that threshold if you want to whatever makes sense in your environment. (That is whatever keeps it from running multiple invocations at once.)
 
Old 04-11-2012, 10:59 AM   #3
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
Also your if can be simplified as it is itself a function which tests for truth:
Code:
if pidof process_name
You can put the not in or just change the if and else actions. Also, you may wish to redirect the output to /dev/null as we are not concerned with displaying it.
 
Old 04-11-2012, 12:16 PM   #4
jlacroix
Member
 
Registered: Nov 2003
Posts: 187

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by MensaWater View Post
Code:
#!/bin/bash
# init

while true
do if [ ! "$(pidof process_name)" ]
   then
        echo "I'm doing it."
   else
        echo "I'm not doing it."
   fi
sleep 300
done
The while loop say to keep doing something until a condition is no longer valid. Using the keyword "true" means it is always valid so it will do it forever. You want to put a sleep as a governor. Mine is 300 seconds (5 minutes). You can lower that threshold if you want to whatever makes sense in your environment. (That is whatever keeps it from running multiple invocations at once.)
Thanks guys, but I don't really think I want a while statement, unless I'm misunderstanding. My understanding is that there are two processes (may determine more later) that may be running, and if they are, I want my script to just exit and not do anything. Is there a way to basically say something like:

if ! process_1 process_2 process_3
then
blah blah blah
else
exit
fi
 
Old 04-11-2012, 01:06 PM   #5
MensaWater
LQ Guru
 
Registered: May 2005
Location: Atlanta Georgia USA
Distribution: Redhat (RHEL), CentOS, Fedora, CoreOS, Debian, FreeBSD, HP-UX, Solaris, SCO
Posts: 7,831
Blog Entries: 15

Rep: Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669
You don't need an else/exit. If you have only a then it will do the blah blah blah otherwise it will simply exit.

Maybe I misunderstood - I thought you were asking how to check this frequently rather than one time. If you just want to check it one time then doing the if without the else should suffice. On reread it appears you just want to check any one of several processes. How are you getting the list of processes? How are you getting the pidof the process? That isn't in what you gave us.

You could allow the process name to be input at command line:

Code:
for process_name in $@
do if [ ! "$(pidof $process_name)" ]
   then
        echo "I'm doing it."
   else
        echo "I'm not doing it."
   fi
sleep 300
done
The $@ is shell shorthand for all arguments passed in at invocation. So if your script name was doit.sh you could run:
doit.sh ls df who

And it would then check for the ls, df and who in each successive run of the loop.
You could do
#!/bin/bash
# init

fwhile true
do if [ ! "$(pidof process_name)" ]
then
echo "I'm doing it."
else
echo "I'm not doing it."
fi
sleep 300
done
 
Old 04-11-2012, 01:50 PM   #6
jlacroix
Member
 
Registered: Nov 2003
Posts: 187

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by MensaWater View Post
You don't need an else/exit. If you have only a then it will do the blah blah blah otherwise it will simply exit.

Maybe I misunderstood - I thought you were asking how to check this frequently rather than one time. If you just want to check it one time then doing the if without the else should suffice. On reread it appears you just want to check any one of several processes. How are you getting the list of processes? How are you getting the pidof the process? That isn't in what you gave us.

You could allow the process name to be input at command line:

Code:
for process_name in $@
do if [ ! "$(pidof $process_name)" ]
   then
        echo "I'm doing it."
   else
        echo "I'm not doing it."
   fi
sleep 300
done
The $@ is shell shorthand for all arguments passed in at invocation. So if your script name was doit.sh you could run:
doit.sh ls df who

And it would then check for the ls, df and who in each successive run of the loop.
You could do
#!/bin/bash
# init

fwhile true
do if [ ! "$(pidof process_name)" ]
then
echo "I'm doing it."
else
echo "I'm not doing it."
fi
sleep 300
done
I get the name of the process from this line:
Code:
if [ ! "$(pidof process_name)" ]
So if the process was "myprogram" that line would read:
Code:
if [ ! "$(pidof myprogram)" ]
 
Old 04-11-2012, 01:59 PM   #7
MensaWater
LQ Guru
 
Registered: May 2005
Location: Atlanta Georgia USA
Distribution: Redhat (RHEL), CentOS, Fedora, CoreOS, Debian, FreeBSD, HP-UX, Solaris, SCO
Posts: 7,831
Blog Entries: 15

Rep: Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669
OK so if you want to hard code the names you can do that:

Code:
for process_name in myprogram yourprogram anybodysprogram
do if [ ! "$(pidof $process_name)" ]
   then
        echo "I'm doing it."
   else
        echo "I'm not doing it."
   fi
sleep 5
done
That would do the loop and check each of myprogram, yourprogram and anybodysprogram.
 
Old 04-11-2012, 02:08 PM   #8
jlacroix
Member
 
Registered: Nov 2003
Posts: 187

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by MensaWater View Post
OK so if you want to hard code the names you can do that:

Code:
for process_name in myprogram yourprogram anybodysprogram
do if [ ! "$(pidof $process_name)" ]
   then
        echo "I'm doing it."
   else
        echo "I'm not doing it."
   fi
sleep 5
done
That would do the loop and check each of myprogram, yourprogram and anybodysprogram.
Ok, so if I am understanding that script correctly, if any of myprogram, yourprogram, anybodysprogram is running, the script will print "I'm not doing it." If none of them are running, it will print "I'm doing it." If so, then your script is exactly what I want.

Last edited by jlacroix; 04-11-2012 at 02:11 PM.
 
Old 04-11-2012, 02:34 PM   #9
MensaWater
LQ Guru
 
Registered: May 2005
Location: Atlanta Georgia USA
Distribution: Redhat (RHEL), CentOS, Fedora, CoreOS, Debian, FreeBSD, HP-UX, Solaris, SCO
Posts: 7,831
Blog Entries: 15

Rep: Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669
It will print "I'm doing it" for each of them that is running and "I'm not doing it" for each of them that is not running. That means it could give you:

I'm doing it
I'm doing it
I'm doing it
--OR--
I'm not doing it
I'm not doing it
I'm not doing it
--OR--
I'm doing it
I'm not doing it
I'm doing it
--OR--
I'm not doing it
I'm doing it
I'm doing it
--OR--
etc...

It sounds now as if you want to only do the I'm doing it if ALL are running rather than if EACH is running? For that you'd want to do something slightly different:
Code:
CNT=0
for process_name in myprogram yourprogram anybodysprogram
do if [ ! "$(pidof $process_name)" ]
   then
        CNT=$(expr $CNT + 1)
   fi
done
if [ $CNT -eq 3 ]
then
    echo "I'm doing it."
else
    echo "I'm not doing it."
fi
In that script you're simply incrementing a counter for each program it finds running. If all 3 are running then the counter becomes 3 and it prints "I'm doing it". If the counter is anything else (presumably less than 3) then it would print "I'm not doing it".
 
Old 04-11-2012, 05:57 PM   #10
jlacroix
Member
 
Registered: Nov 2003
Posts: 187

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by MensaWater View Post
It will print "I'm doing it" for each of them that is running and "I'm not doing it" for each of them that is not running. That means it could give you:

I'm doing it
I'm doing it
I'm doing it
--OR--
I'm not doing it
I'm not doing it
I'm not doing it
--OR--
I'm doing it
I'm not doing it
I'm doing it
--OR--
I'm not doing it
I'm doing it
I'm doing it
--OR--
etc...

It sounds now as if you want to only do the I'm doing it if ALL are running rather than if EACH is running? For that you'd want to do something slightly different:
Code:
CNT=0
for process_name in myprogram yourprogram anybodysprogram
do if [ ! "$(pidof $process_name)" ]
   then
        CNT=$(expr $CNT + 1)
   fi
done
if [ $CNT -eq 3 ]
then
    echo "I'm doing it."
else
    echo "I'm not doing it."
fi
In that script you're simply incrementing a counter for each program it finds running. If all 3 are running then the counter becomes 3 and it prints "I'm doing it". If the counter is anything else (presumably less than 3) then it would print "I'm not doing it".
I want it to print "I'm doing it" if ALL of the three are NOT running. If any of the three ARE running, I want it to print "I'm not doing it." I don't want it to loop, I want it to do one or the other just once.

Basically (long story made short), I'll be writing a script that shouldn't run if certain programs are running.
 
Old 04-12-2012, 07:36 AM   #11
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
So we are back to the simple if state:
Code:
if pidof myprogram yourprogram anybodysprogram 2>&1 /dev/null
then
    echo "I'm not doing it."
else
    echo "I'm doing it."
fi
 
Old 04-12-2012, 07:44 AM   #12
MensaWater
LQ Guru
 
Registered: May 2005
Location: Atlanta Georgia USA
Distribution: Redhat (RHEL), CentOS, Fedora, CoreOS, Debian, FreeBSD, HP-UX, Solaris, SCO
Posts: 7,831
Blog Entries: 15

Rep: Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669
It is not necessary to quote entire posts in your replies. The thread has the earlier post.

It should be obvious what you need to do given what I provided previously. Simply change the final conditional from:

Code:
if [ $CNT -eq 3 ]
then
    echo "I'm doing it."
else
    echo "I'm not doing it."
fi
to:

Code:
if [ $CNT -eq 0 ]
then
    echo "I'm doing it."
else
    echo "I'm not doing it."
fi
That way it does the "I'm doing it" only when none of the processes is running from the for loop above this conditional.

The [ ] syntax is short for "test". You can find the meaning of -eq, -gt, -lt etc... by typing "man test". Note that in test these are used for numeric comparisions where "=", ">", "<" are used for string comparisons.

As a final note I'd suggest leaving out contractions in your scripts as the single quote (apostrophe) has special meaning so can sometimes cause unexpected results. That is to say - use:
echo "I am doing it."
rather than:
echo "I'm doing it."
 
Old 04-12-2012, 09:08 AM   #13
jlacroix
Member
 
Registered: Nov 2003
Posts: 187

Original Poster
Rep: Reputation: 15
Unfortunately, when I try that code I get no output at all, even when I change one of the program names to a program I know for sure is running.

When I try this (the one posted prior to yours by grail):
Code:
if pidof myprogram yourprogram anybodysprogram 2>&1 /dev/null
then
    echo "I'm not doing it."
else
    echo "I'm doing it."
fi
I get no output with that one either. However, that code looks simple and closer to what I need. The first line appears to be testing if any of the three are running, and then it will print one of the two strings based on the test. However, I think we're close. Perhaps there is some form of an "or" statement needed between each program name?

Just curious, why is the 2>&1 /dev/null portion necessary?

Thanks guys, I'm a bit new to scripting but this is helping.
 
Old 04-12-2012, 09:21 AM   #14
MensaWater
LQ Guru
 
Registered: May 2005
Location: Atlanta Georgia USA
Distribution: Redhat (RHEL), CentOS, Fedora, CoreOS, Debian, FreeBSD, HP-UX, Solaris, SCO
Posts: 7,831
Blog Entries: 15

Rep: Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669Reputation: 1669
When you try "that code"? Did you just do the conditional I last posted or did you do my original post and modify the conditional as I instructed? Clearly you seem to want us to write the script for you rather than trying to test things on your own.

Programs have "file descriptors" of which a couple of very important ones are file descriptor 1 (standard output a/k/a stdout) and file descriptor 2 (standard error a/k/a stderr). The ">/dev/null" is shorthand for 1>/dev/null so it is saying to send stdout to /dev/null. The 2>&1 is shorthand for redirecting stderr to stdout so it is also going to /dev/null because stdout was sent there.

At this point I'd suggest you go look at one of the many tutorials for shell scripting like:
http://www.freeos.com/guides/lsst/
 
Old 04-12-2012, 09:41 AM   #15
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
I must say I am a little confused too. As the format of if would imply, you must get at least one of the two lines being echoed as there are only two choices, true or false.

So just to confirm, you have a script, called test_script.sh (for example), that looks like:
Code:
#!/bin/bash

if pidof myprogram yourprogram anybodysprogram 2>&1 /dev/null
then
    echo "I'm not doing it."
else
    echo "I'm doing it."
fi
Now another assumption here is that you are changing myprogram, yourprogram and anybodysprogram to be actual programs that pidof can find (or run as is and get the negative solution I guess)

This file you have made executable with something like:
Code:
$ chmod 755 test_script.sh
And then you have run it by issuing:
Code:
$ ./test_script.sh
After running the above on my computer I get:
Code:
$ ./test_script.sh
I'm doing it.
Which is expected as none of three mentioned programs are running on my machine.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
quick bash script to convert flac to mp3 zuralin Programming 8 08-19-2011 03:50 AM
SSH connection from BASH script stops further BASH script commands tardis1 Linux - Newbie 3 12-06-2010 08:56 AM
A quick bash question Ander Linux - Newbie 6 05-05-2006 02:13 AM
Quick bash help Aphex_Twin2 Linux - General 5 05-23-2005 10:59 AM
quick bash help! frost33 Programming 2 11-14-2002 06:24 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:05 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration