LinuxQuestions.org
Help answer threads with 0 replies.
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 11-06-2008, 12:19 PM   #1
jlarsen
Member
 
Registered: Jan 2005
Location: Dallas, TX
Distribution: Slackware 13.0
Posts: 76

Rep: Reputation: 15
bash - difference between executing program in for loop and typing each command?


I'm trying to use a script to call a program (which is done in C by somebody else), and have trouble when trying to use a for loop.

The program being called by the script looks for a configuration file in the directory from which it is called. The script just changes directories then it runs the same program. The syntax of the loop seems OK, but it never gets past the first call of the program.

Basic idea is:

Code:
cd /path/to/cfgdir1
/path/to/program
cd /path/to/cfgdir2
/path/to/program
It works like that, but when I put it in a for loop it never makes it to the second call of the program, like control is never returned to the script?


Code:
#!/bin/bash
#
progdir=( ex1 ex2 ex3 ex4 ex5 )

for (( i = 0 ; i < ${#progdir[@]} ; i++ )); do
   cd /path/to/cfgdir/${progdir[$i]}
   /path/to/program
   echo "finished with ${progdir[$i]}"
   sleep 2
done
exit
I get the last output from the program being called, but I do not ever get output from echo.

Any ideas?
Thanks in advance.

Last edited by jlarsen; 11-06-2008 at 02:24 PM.
 
Old 11-06-2008, 01:23 PM   #2
jailbait
Guru
 
Registered: Feb 2003
Location: Blue Ridge Mountain
Distribution: Debian Wheezy, Debian Jessie
Posts: 7,592

Rep: Reputation: 188Reputation: 188
I gave an incorrect answer.

-----------------
Steve Stites

Last edited by jailbait; 11-06-2008 at 01:24 PM.
 
Old 11-06-2008, 01:32 PM   #3
jlarsen
Member
 
Registered: Jan 2005
Location: Dallas, TX
Distribution: Slackware 13.0
Posts: 76

Original Poster
Rep: Reputation: 15
I have tried again with a simplified version of the script to make troubleshooting a little easier, but still the same result. Here is the new version:

Code:
#!/bin/bash
#
for progdir in ex1 ex2 ex3 ex4 ex5; do
   cd /path/to/cfgdir/$progdir
   /path/to/program
   echo "finished with $progdir"
   sleep 1
done

exit
I'm not positive if it is the script or that the C program being called needs to exit properly to give control back to the script. Still puzzled why it works when typing the instructions line by line in a script though......maybe the for loop forks the process and it never comes back? Dont' know, I have limited understanding of how all that works.

Last edited by jlarsen; 11-06-2008 at 02:25 PM. Reason: added code tags
 
Old 11-06-2008, 02:16 PM   #4
jan61
Member
 
Registered: Jun 2008
Posts: 235

Rep: Reputation: 46
Moin,

first you should rename your loop counter. test is a shell builtin, you get into trouble using it as a variable name.

Jan
 
Old 11-06-2008, 02:22 PM   #5
jlarsen
Member
 
Registered: Jan 2005
Location: Dallas, TX
Distribution: Slackware 13.0
Posts: 76

Original Poster
Rep: Reputation: 15
Thanks for the reply, but I did not use test in the actual script. I was just trying to make it easier to read. I will edit original post to reflect this.
 
Old 11-06-2008, 02:29 PM   #6
jlarsen
Member
 
Registered: Jan 2005
Location: Dallas, TX
Distribution: Slackware 13.0
Posts: 76

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by jlarsen View Post
maybe the for loop forks the process and it never comes back?
So much for that theory, I've been reading the Bash Guide at gnu.org and found this:

Quote:
Since Bash is a completely new implementation, it does not suffer from many of the limitations of the SVR4.2 shell. For instance:

* Bash does not fork a subshell when redirecting into or out of a shell control structure such as an if or while statement.
 
Old 11-06-2008, 02:29 PM   #7
jan61
Member
 
Registered: Jun 2008
Posts: 235

Rep: Reputation: 46
Moin,

Quote:
Originally Posted by jlarsen View Post
Thanks for the reply, but I did not use test in the actual script. I was just trying to make it easier to read. I will edit original post to reflect this.
place a "set -x" line before the loop, this tells the bash to write every command, like it's invoked, on stderr. Watch the output and post it here if you don't find the reason for the "unexpected behaviour".

Jan
 
Old 11-06-2008, 06:17 PM   #8
jlarsen
Member
 
Registered: Jan 2005
Location: Dallas, TX
Distribution: Slackware 13.0
Posts: 76

Original Poster
Rep: Reputation: 15
While looking at the output generated by running the script with "set -x", I found some other output I missed earlier from the program that is called by the script.

Code:
 Trying to kill an old running myprogram process ID='29243'
Terminated
root@bkloaner:/path/to/myprogram#
 Killed old 'myprogram' process ID='29243'
Turns out the program being called checks to see if there another instance of itself before starting, and then kills it. I don't have any control over the way that program works, so now my question is:

How do I make sure that the first instance of the program myprogram is allowed to finish running before the next is started?
 
Old 11-06-2008, 06:35 PM   #9
chrism01
Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.6, Centos 5.10
Posts: 16,324

Rep: Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041
You could try
Code:
ps -ef|grep /path/name_of_program|grep -v grep
if [[ $? -eq 0 ]]
then 
    echo "prog already running"
else
    run_it
fi
You can expand that using awk to get the pid if you want to kill it, if its safe to do so.
 
Old 11-07-2008, 01:45 PM   #10
jan61
Member
 
Registered: Jun 2008
Posts: 235

Rep: Reputation: 46
Moin,

Quote:
Originally Posted by chrism01 View Post
...
Code:
ps -ef|grep /path/name_of_program|grep -v grep
...
A more comfortable way is pidof. And with this little extension you can forget the grep -v grep:
Code:
ps -ef|grep [/]path/name_of_program
Jan
 
Old 11-07-2008, 04:06 PM   #11
jlarsen
Member
 
Registered: Jan 2005
Location: Dallas, TX
Distribution: Slackware 13.0
Posts: 76

Original Poster
Rep: Reputation: 15
Thanks for the tips!

I could possibly put the code given in a while loop and just keep checking until it is OK to run myprogram.

Part of the problem is that I don't understand when a child process is made, which seems to be the problem in this situation. From what I can tell


Code:
cd /path/to/cfgdir1
/path/to/myprogram
cd /path/to/cfgdir2
/path/to/myprogram
will change directories, execute /path/to/myprogram, when myprogram finishes, it will change directories again, then execute /path/to/myprogram again, etc.

The for loop, however, seems to create multiple child processes, and since /path/to/myprogram will kill any already existing instances of itself, I run into problems. Am I understanding this correctly?

If so, what I would like is a way to tell bash not to create child processes, or to wait until the first one completes before starting the second one.

I have tried using "wait" both before or after calling myprogram, but either I am using it incorrectly or this is not what I need.
 
Old 11-08-2008, 01:19 AM   #12
The_Kernel
LQ Newbie
 
Registered: Nov 2008
Posts: 19

Rep: Reputation: 0
To use "wait" you need to start the preceding command in the background by adding an '&' to the end of the command. Like this:

Code:
cd /path/to/cfgdir1
/path/to/myprogram &
MY_PID="$!"
wait $MY_PID
 
Old 11-10-2008, 12:09 PM   #13
jlarsen
Member
 
Registered: Jan 2005
Location: Dallas, TX
Distribution: Slackware 13.0
Posts: 76

Original Poster
Rep: Reputation: 15
Well, I finally figured out why the script with each line typed out (instead of a for loop) was working and it had nothing to do with the loop. The first script did not have the #!/bin/bash at the top. I removed this from the script with the for loop and now it executes each command in order, instead of making a bunch of child processes and running them at the same time.

I understand using #!/bin/bash specifies the program that interprets the commands in the script, but what is used when nothing is specified?
 
Old 11-10-2008, 06:19 PM   #14
chrism01
Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.6, Centos 5.10
Posts: 16,324

Rep: Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041Reputation: 2041
It uses the default shell ie whichever one you are currently logged in with. You can use
echo $SHELL
or
grep yourusername /etc/passwd
to check which one.
 
Old 11-10-2008, 06:38 PM   #15
jlarsen
Member
 
Registered: Jan 2005
Location: Dallas, TX
Distribution: Slackware 13.0
Posts: 76

Original Poster
Rep: Reputation: 15
That is strange, both of those show that I am using /bin/bash

However, once I remove the #!/bin/bash (without editing anything else) the script works. I also noticed the original script that just writes out command without the for loop does not work if I add #!/bin/bash. This may end up going unsolved, but here is the script I am using now just in case it matters to anyone:

Code:
# runs myprog for each site
#
sites=( ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex7 ex8 ex9 )

#set -x
for (( i = 0 ; i < ${#sites[@]} ; i++ )); do
   cd /path/to/different/cfg/dirs/${sites[$i]}
   /path/to/myprogram &
   MY_PID="$!"
   wait $MY_PID
done
exit
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
Command for executing C program in crontab bhandu Linux - Newbie 1 07-14-2007 01:54 PM
Know of a command executing program for LIRC? Titan2k Linux - Software 2 04-07-2007 09:11 PM
Loop Bash command to hit... rumperpumper Linux - General 4 01-31-2006 09:39 PM
Trivial bash question - executing $COMMAND atom Programming 4 06-05-2005 05:17 AM
typing a program name in the command prompt to run it iammeuno Linux - Newbie 1 12-19-2003 02:11 PM


All times are GMT -5. The time now is 07:37 PM.

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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration