Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

exec function does not return command prompt

by casman46 (Initiate)
on Aug 15, 2014 at 18:33 UTC ( [id://1097603]=perlquestion: print w/replies, xml ) Need Help??

casman46 has asked for the wisdom of the Perl Monks concerning the following question:

I am experimenting with using the fork and exec functions to spawn a child process and execute a different script. My ultimate goal is to spawn multiple child processes from the parent without waiting for any of the children to complete. My first attempt is to merely spawn a single child. The parent code is as follows:

#!/usr/bin/perl use strict; use warnings; my $pid; if( $pid = fork ){ print "In test1 the parent pid is $$; the child pid is $pid\n"; } else { die "could not fork a process: $!" unless defined $pid; exec ( "/liwidata/dev/tmp/jmg/dev/library/test2.pl" ) or print STD +ERR "couldn't exec test program: $!"; } print "All done!\n";

The child code is as follows:

#!/usr/bin/perl use strict; use warnings; print "In test2.pl the pid is $$\n";

When I execute the parent script I receive the following output:

/liwidata/dev/tmp/jmg/dev/library> ./test1.pl In test1 the parent pid is 21348; the child pid is 21349 All done! /liwidata/dev/tmp/jmg/dev/library> In test2.pl the pid is 21349

As you can see the command prompt does not appear at the conclusion of the child script. I must enter a Ctrl-C in order to get it back. What am I doing wrong?

Replies are listed 'Best First'.
Re: exec function does not return command prompt
by Crackers2 (Parson) on Aug 16, 2014 at 01:05 UTC
    When I execute the parent script I receive the following output:
    /liwidata/dev/tmp/jmg/dev/library> ./test1.pl In test1 the parent pid is 21348; the child pid is 21349 All done! /liwidata/dev/tmp/jmg/dev/library> In test2.pl the pid is 21349
    As you can see the command prompt does not appear at the conclusion of the child script.

    Are you sure? To me it looks like the prompt is right there, _before_ the "In test2.pl" output.

    Instead of Ctrl-C, have you tried just entering a command? (or pressing enter to simply go to the next line)

      Crackers2: Thank you for your reply to my question. It appears that I do not understand how the fork function works. Nevertheless, since both test1.pl and test2.pl do exit, shouldn't I see a command prompt at the conclusion of each one?

        No. That's not how the shell works. Either it will wait for both to exit before showing the (one) prompt, or it will show the prompt after a certain proces exits and finish the other one in the background; in that case you won't get a new prompt after the background one exits.

        I'm not exactly sure when it decides to keep stuff in the foreground or run them in the background.

        In your case I think it's running both in the foreground, but due to buffering the output from test2 just happens to show up after the prompt

Re: exec function does not return command prompt
by kbrannen (Beadle) on Aug 15, 2014 at 18:47 UTC
    Look at "perldoc -f wait" and then add that to your code at the bottom. I think you'll like that better. :)

      Better yet, if you're going to try to do something with multiple children, here's an example to speed you up. Create a file for input with a number of sleep commands with random values, then test.

      #!/usr/bin/perl # multi.pl # usage: multi.pl [max_tasks] < job_list # max_task defaults to 4 # # do all the jobs as quickly as possible in parallel, but no more than # max_tasks at a time. use warnings; use strict; sub mysystem { my $cmd = shift; my $pid; #print "forking: $cmd\n"; if (($pid = fork()) == 0) { exec($cmd); } # child return $pid; # parent } # how many tasks can we do at once my $max_tasks = 4; if (defined($ARGV[0])) { $max_tasks = shift(@ARGV); } # num of curr tasks my $num_tasks = 0; # pids running, and command run my %pids = (); my ($pid, $cmd); # read tasks while ($cmd = <>) { chomp($cmd); # execute the task print "starting: $cmd\n"; $pid = mysystem($cmd); #print "forked pid $pid\n"; $pids{$pid} = $cmd; $num_tasks++; # if we're doing all we should, wait for 1 to end while ($num_tasks >= $max_tasks) { $pid = wait(); #print "reaped pid $pid\n"; last if ($pid == -1); # error? print "finished: $pids{$pid}\n"; delete($pids{$pid}); $num_tasks--; } } # wait for all children to end while ($num_tasks > 0) { $pid = wait(); last if ($pid == -1); # error? print "finished: $pids{$pid}\n"; delete($pids{$pid}); $num_tasks--; } exit(0);
      Example test file:
      sleep 4 sleep 2 sleep 6 sleep 3 sleep 4 sleep 2
      Test run: perl multi.pl 2 < test_file_above

        kbrannen: thank you for your lengthy example; it is most helpful. I will experiment with this code in the context of my project.

Re: exec function does not return command prompt (!child)
by tye (Sage) on Aug 16, 2014 at 01:02 UTC

    I didn't see where anybody actually explained the source of your problem (just suggest alternatives).

    The problem is that you have the parent doing exec and have the child just say "In test1..." and then "All done!". The child exits, not the parent. The parent continues on running test2.pl. So you won't get a prompt back until test2.pl exits.

    Update: Actually, I believe I am mistaken and that Crackers2 is correct.

    - tye        

      Tye: Thank you for your explanation of my problem. As I noted in my reply to Crackers2, it is obvious that I do not understand how the fork function works! However, it seems odd that only one command prompt appears even though both scripts exit.

Re: exec function does not return command prompt
by Anonymous Monk on Aug 15, 2014 at 21:27 UTC

      Anonymous Monk: Thank you for your suggestion. I did not know this module existed. It appears to simplify the fork/exec process considerably. I will experiment with the use of this module in the context of my project.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1097603]
Front-paged by GotToBTru
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (6)
As of 2024-03-28 20:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found