Home > Back-end >  Perl Windows alternatives for "system" ( opening multiple processes )
Perl Windows alternatives for "system" ( opening multiple processes )

Time:10-23

So long story short, I'm trying to run a linux perl script in Windows ( with few modifications ).

On Unix it works just fine, but on Windows I come to the conclusion that calling for system doesn't work the same as on Unix and so it doesn't create multiple processes.

Below is the code :

use strict;
use warnings;
open (FIN, 'words.txt'); while (<FIN>) {
   chomp;
   my $line = $_;
   system( "perl script.pl $line &" );
   
}
close (FIN);

So basically, I have 5 different words in "words.txt" which I want each and every one to be used one by one when calling for script.pl , which means :

word1 script.pl
word2 script.pl
word3 script.pl
etc

As of now it opens just the first word in words.txt and it loops with that one only. As I said, on Unix it works perfectly, but not on Windows.

I've tried to use "start" system( "start perl script.pl $line &" ); and it works...except it opens 5 additional CMDs to do the work. I want it to do the work on the same window.

If anyone has any idea how this can work on window, i'll really appreciate it.

Thanks!

CodePudding user response:

According to perlport :

system

(Win32) [...] system(1, @args) spawns an external process and immediately returns its process designator, without waiting for it to terminate. Return value may be used subsequently in wait or waitpid. Failure to spawn() a subprocess is indicated by setting $? to 255 << 8. $? is set in a way compatible with Unix (i.e. the exit status of the subprocess is obtained by $? >> 8, as described in the documentation).

I tried this:

use strict;
use warnings;
use feature qw(say);
say "Starting..";
my @pids;
for my $word (qw(word1 word2 word3 word3 word5)) {
    my $pid = system(1, "perl script.pl $word" );
    if ($? == -1) {
        say "failed to execute: $!";
    }
    push @pids, $pid; 
}

#wait for all children to finish
for my $pid (@pids) {
    say "Waiting for child $pid ..";
    my $ret = waitpid $pid, 0;
    if ($ret == -1) {
        say " No such child $pid";
    }
    if ($? & 127) {
        printf " child $pid died with signal %d\n", $? & 127;
    }
    else {
        printf " child $pid exited with value %d\n", $? >> 8;
    }
}
say "Done.";

With the following child script script.pl :

use strict;
use warnings;
use feature qw(say);
say "Starting: $$";
sleep 2 int(rand 5);
say "Done: $$";
sleep 1;
exit int(rand 10);

I get the following output:

Starting..
Waiting for child 7480 ..
Starting: 9720
Starting: 10720
Starting: 9272
Starting: 13608
Starting: 13024
Done: 13608
Done: 10720
Done: 9272
Done: 9720
Done: 13024
 child 7480 exited with value 9
Waiting for child 13344 ..
 child 13344 exited with value 5
Waiting for child 17396 ..
 child 17396 exited with value 3
Waiting for child 17036 ..
 child 17036 exited with value 6
Waiting for child 17532 ..
 child 17532 exited with value 8
Done.

Seems to work fine..

CodePudding user response:

You can use Win32::Process to get finer control over creating a new process than system gives you on Windows. In particular, the following doesn't create a new console for each process like using system("start ...") does:

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
# Older versions don't work with an undef appname argument.
# Use the full path to perl.exe on them if you can't upgrade
use Win32::Process 0.17; 

my @lines = qw/foo bar baz quux/; # For example instead of using a file
my @procs;
for my $line (@lines) {
    my $proc;
    if (!Win32::Process::Create($proc, undef, "perl script.pl $line", 1,
                                NORMAL_PRIORITY_CLASS, ".")) {
        $_->Kill(1) for @procs;
        die "Unable to create process: $!\n";
    }
    push @procs, $proc;
}

$_->Wait(INFINITE) for @procs;
# Or
# use Win32::IPC qw/wait_all/;
# wait_all(@procs);


As Yet Another Way To Do It, the start command takes a /b option to not open a new command prompt.

system("start /b perl script.pl $line");
  • Related