Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Executing a command after the preceding command finished processing

by Locutus_ (Initiate)
on Mar 29, 2018 at 23:36 UTC ( [id://1212005]=perlquestion: print w/replies, xml ) Need Help??

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

I am creating a basic Perl script for a capstone project to automate a few different Unix commands that need to be executed in a specific order.

Using system() to call these commands:

system("nohup scripts_pl/RunAll.pl &");

This is one of two commands that needs time to finish processing before the rest of the script can run. It is in its own subroutine so this part of the code can be run with a flag, although there is another flag to run the entire script (the line below behaves similarly):

system("nohup run_decode.pl $shortDir $shortDir $senone &");

This line also executes a Unix command that needs time to process before the next (and final) line should execute. That isn't the case which is resulting in erroneous data for my project; the command is executed and the process runs in the background but the final line executes before it finishes.

I'd like a print statement "X has finished processing" to follow each of these commands once they have finished processing so the user knows they have successfully processed and the code can safely continue compiling (or the user can execute another part of the code with a different flag).

I hope this is clear enough. Thank you!

Replies are listed 'Best First'.
Re: Executing a command after the preceding command finished processing
by codiac (Beadle) on Mar 30, 2018 at 04:43 UTC
    If you want the Perl script to wait for the shell command to complete then the easiest way is to remove the ampersand '&' from the command.
Re: Executing a command after the preceding command finished processing
by Laurent_R (Canon) on Mar 30, 2018 at 06:26 UTC
    Just a naive question: why do you run your system commend in the background if you want to wait for it to complete before you proceed? In other words, it seems to me that you don't really need the ampersand and the nohup statement. If you remove them, your Perl script will wait for the system command to complete before proceeding to execute the next code statement. In a way, this is not a Perl question, since you would have the same problem if you did that in a shell script.

    Just as a side comment, please note that ¨Perl is compiling the whole script before it starts executing anything (except for special phaser blocks such as BEGIN { ...}).

    Update: fixed a typo.

Re: Executing a command after the preceding command finished processing
by choroba (Cardinal) on Mar 29, 2018 at 23:46 UTC
    Just print the message from the background process:
    system '( nohup sleep 5 ; echo Shell done. ) &'; print "Perl done.\n";
    Beware: The message can appear in the middle of the command line. Precede it with a newline to prevent it, but it can still do weird things if you e.g. run mc in the meantime.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      Thanks for the prompt reply.

      I'm just confused as to where the code you provided would be placed in relation to the lines I provided. The two lines I provided both have a Perl script that is executed. Would your code follow my code or does it need to be placed elsewhere?

Re: Executing a command after the preceding command finished processing
by mr_ron (Chaplain) on Mar 30, 2018 at 12:51 UTC

    If you want to run the two programs at the same time and wait for both on a system with UNIX shell (wfm on bash and csh) you might try something like:

    perl -e 'system q/\ (sleep 5; echo after 5) &\ (sleep 2; echo after 2) &\ wait; echo all done\ /'
    Ron
Re: Executing a command after the preceding command finished processing
by bliako (Monsignor) on Mar 31, 2018 at 09:10 UTC

    The first point to consider will be codiac's comment: why do you need to run your processes in the background (the & at the end of your system() calls).

    If you do need these ampersands it means you have to wait()/waitpid() on them to finish. Otherwise you seriously run the risk of your perl program reaching its end and terminating while your sub-processes spawned with system() have not yet finished.

    So, the pattern would be: obtain the PID of each spawned command and waitpid() for it. When waitpid() has returned, it means process with that PID has finished and you then print your messages.

    A good question would be how to get the PID of the command spawned by system(). A suggestion can be found in marufcetin's comment and also in this node http://www.perlmonks.org/?node_id=680938 which has this:

    my $pid = open my $cmd, "-|", 'ls -al' or die $!;

    Note: "If the "open" involved a pipe, the return value happens to be the pid of the subprocess.", from the perlfunc manual.

    Alternatively, the "purest" way would be to fork() first and system() within, without the ampersands. Then, all you have to do is to wait on the forked pid. This is demonstrated in this node: http://www.perlmonks.org/?node_id=671047

    And if all these forks look scary, you can use a high level module such as Parallel::ForkManager or similar (e.g. Parallel::Simple) to spawn your system() commands without the ampersands and wait for them to finish.

    However, from the code you supplied it looks to me that you can improve on your design a lot especially those ampersands...

Re: Executing a command after the preceding command finished processing
by haukex (Archbishop) on Apr 01, 2018 at 10:30 UTC
Re: Executing a command after the preceding command finished processing
by mr_ron (Chaplain) on Mar 31, 2018 at 19:43 UTC
    I wonder if a basic point here still needs clarification:
    I am creating a basic Perl script ... to automate a few different Unix commands that need to be executed in a specific order.

    Using system() to call these commands:

    system("nohup scripts_pl/RunAll.pl &");
    Do the commands invoked by system need to be executed in a specific order with respect to each other or does the calling script want to run them in parallel before it moves on to other processing? If the invoked scripts need to run in order or don't need to run in parallel then codiac's post may be all you need. If it is the latter case then we need to look at somewhat a more involved approach like some of the other posts suggesting open, shell process control, or fork.
    Ron
Re: Executing a command after the preceding command finished processing
by marufcetin (Initiate) on Mar 30, 2018 at 09:56 UTC
    try as
    open PIPE, "| nohup run_decode.pl";
    
Re: Executing a command after the preceding command finished processing
by karthiknix (Sexton) on Apr 03, 2018 at 16:10 UTC

    In your case I would suggest to find out the process id for the previous command or dependent command you are running. Wait until that process is complete then go for the next command to execute.

Re: Executing a command after the preceding command finished processing
by Anonymous Monk on Mar 30, 2018 at 14:00 UTC
    You cannot reliably suspend Perl compiling until another command runs – I do not think that BEGIN would serve you here. Instead, run the predecessor command, then run the Perl script.

      You really should hush.

      # File: Mod.pm package Mod; sub import { print `date`; sleep 10 }; 1; # File: code.pl BEGIN { print `date` } use Mod; I'm a little tea pot. # Command line- moo@cow~>perl code.pl || date Fri Mar 30 09:37:09 PDT 2018 Fri Mar 30 09:37:09 PDT 2018 syntax error at code.pl line 3, at EOF Execution of code.pl aborted due to compilation errors. Fri Mar 30 09:37:19 PDT 2018
      I think that the OP really meant "execute," not "compile":
      ... needs time to process before the next (and final) line should compile execute...
        I did indeed mean execute, sorry about that. Corrected.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-04-19 05:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found