Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 从Perl线程运行bash脚本_Multithreading_Bash_Perl - Fatal编程技术网

Multithreading 从Perl线程运行bash脚本

Multithreading 从Perl线程运行bash脚本,multithreading,bash,perl,Multithreading,Bash,Perl,我的脚本应该有n个子例程(My_proc)同时运行,每个子例程运行bash脚本,一个子例程(check_procs)检查子例程是否完成 use strict; use threads; use threads::shared; my %proc_status :shared; my %thr; foreach my $i (1,2,3,4) { $proc_status{$i}=0; } sub my_proc { my $arg=shift(@_); while

我的脚本应该有n个子例程(My_proc)同时运行,每个子例程运行bash脚本,一个子例程(check_procs)检查子例程是否完成

use strict;
use threads;
use threads::shared;

my %proc_status :shared;
my %thr;

foreach my $i (1,2,3,4) {
    $proc_status{$i}=0;
}

sub my_proc {
    my $arg=shift(@_);
    while (1) {
         sleep(2);
         print "Proc $arg Started\n";
         #exec("/bin/bash","sleep_for_10_sec.bash") or die("Can't exec");   # case 1
         #`sleep_for_10_sec.bash &`;                                        # case 2      

         print "Proc $arg Finished\n";
         {
         lock(%proc_status);
         $proc_status{$arg}=1;
         }
    }
}

sub check_procs {
    my $all_finished;
    while (! $all_finished) {
            sleep 5;
            print "CHECK: \n";
            $all_finished=1;
            foreach my $num (1,2,3,4) {
                    if ($proc_status{$num} == 1) {
                            print "CHECK: procedure $num has finished\n";
                    } else {
                        $all_finished=0;
                    }
            }
    }
    print "All jobs finished\n";
}

foreach my $num (1,2,3,4) {
    $thr{"$num"} = new threads \&my_proc,$num;
}

my $thr_check= new threads \&check_procs;
$thr_check->join();
这是10秒狂欢的睡眠时间

ls
# bunch of other stuff 
sleep 10
echo "finished sleep"
我不想我的_procsubs等待执行“sleep_等待_10秒bash”命令,浏览后我发现#case1#case2都应该工作,但它们都失败了

#案例1的输出:

#案例2的输出:

但我希望这样:

 Proc 1 Started
 Proc 2 Started
 Proc 3 Started
 Proc 4 Started
 Proc 1 Finished
 Proc 1 Started
 Proc 3 Finished
 Proc 3 Started
 Proc 4 Finished
 Proc 4 Started
 Proc 2 Finished
 Proc 2 Started
 CHECK:
 CHECK:
 CHECK:
 CHECK: procedure 1 has finished
 CHECK: procedure 2 has finished
 CHECK: procedure 3 has finished
 CHECK: procedure 4 has finished
实际上,如果将输出重定向到“>日志”,我会得到想要的结果,但无论如何,在:

 Proc 1 Started
 Proc 2 Started
 Proc 3 Started
 Proc 4 Started
它等待“睡眠等待10秒bash”完成


这是我第一个使用“线程”和“执行”的项目,有人能帮我吗

exec
不应与线程组合
exec
在当前进程中启动一个新程序,因此当您从一个线程调用
exec
时,线程正在执行的程序将消失。由于线程没有要执行的程序,
exec
也会杀死线程

我不清楚为什么案例2不起作用(编辑:见下面ikegami的评论)。我认为它将启动进程,在后台运行,并允许Perl线程立即继续。它似乎没有这样做,但此代码将:

system("/bin/bash sleep_for_10_sec.bash &");        # case 3
exec(“/bin/bash”,“睡眠10秒bash”)或die(“不能执行”)#案例1

exec
用另一个程序替换当前进程中运行的程序。同时,现有线程被终止(因为它们想要执行的程序已经不在了),取而代之的是执行新程序的单个线程

这意味着
exec
永远不会返回(出错时除外)。线程或无线程,
exec
不是您想要的,因为您不希望程序停止运行


但我希望这样:

是否确实要按所需输出指示,每两秒启动
sleep\u 10秒bash
4次(意味着一次最多可以运行20次)

您确定不在乎bash的
sleep\u 10秒
是否完成了所需的输出

如果是这样,为什么要使用线程呢?您可以简单地使用以下内容:

sub start {
   my $num = shift;
   say "Proc $num Started";
   system('bash -c sleep_for_10_sec.bash &');
   say "Proc $num Finished";
}

for my $pass (1..2) {
   start($_) for 1..4;
   sleep 2;
   start($_) for 1..4;
   sleep 2;
   start($_) for 1..4;
   sleep 1;
   if ($pass == 1) {
      say "CHECK:";
   } else {
      say "CHECK: procedure $_ has finished" for 1..4;
   }
}

我想你想要

use threads;

use Thread::Queue qw( );  # 3.01+

use constant NUM_WORKERS => 4;

sub worker {
    my $num = shift;
    say "Job $num Started\n";
    system("sleep_for_10_sec.bash");  # Make sure starts with #! and is executable.
    say "Job $num Finished\n";
}

{
   my $q = Thread::Queue->new();

   for (1..NUM_WORKERS) {
      while (defined( my $job = $q->dequeue() )) {
         worker($job);
      }
   }    

   $q->enqueue(1..4, 1..4);

   $q->end();
   $_->join() for threads->list;
}

Backticks等待孩子的STDOUT关闭,因此它只有在后台程序退出后才会返回(除非你重定向后台程序的STDOUT)。运行
sh-c'/bin/bash sleep_10_sec.bash&'
(就像
system()
调用那样)看起来很愚蠢——为什么要发射两个shell而不是一个呢?@Charles Duffy,因为你说这是一个
bash
脚本。@ikegami,我不是OP。也就是说--Perl没有提供一种直接调用你想要的解释器的方法?(例如,在Python中,我可以直接
subprocess.Popen(['bash','sleep_for_10_sc.bash'])
,只要我不传递
shell=True
就没有隐式
sh-c
)。@Charles Duffy,Python代码是不等价的。您忘记说明
&
。现在,mob可以编写
系统(“/bin/bash-c'sleep'u for_10'u sec.bash&'”
在这种情况下,可以使用
系统('bash','c','sleep_for_10_sec.bash&')
创建两个shell,不过这两个shell都是
bash
。感谢您的详细解释。我终于了解了exec的工作原理(我希望:)#@mob建议的案例3非常有效。不管怎样,你的回答很有启发性,我非常感谢,再次感谢。这是一个糟糕的选择!!!!!如果你同意案例3,那么你应该使用我发布的第一个片段。它只占用了一半的行(23行而不是50行),并且完全避免了使用线程的复杂性(这对您来说是完全无用的)。
sub start {
   my $num = shift;
   say "Proc $num Started";
   system('bash -c sleep_for_10_sec.bash &');
   say "Proc $num Finished";
}

for my $pass (1..2) {
   start($_) for 1..4;
   sleep 2;
   start($_) for 1..4;
   sleep 2;
   start($_) for 1..4;
   sleep 1;
   if ($pass == 1) {
      say "CHECK:";
   } else {
      say "CHECK: procedure $_ has finished" for 1..4;
   }
}
use threads;

use Thread::Queue qw( );  # 3.01+

use constant NUM_WORKERS => 4;

sub worker {
    my $num = shift;
    say "Job $num Started\n";
    system("sleep_for_10_sec.bash");  # Make sure starts with #! and is executable.
    say "Job $num Finished\n";
}

{
   my $q = Thread::Queue->new();

   for (1..NUM_WORKERS) {
      while (defined( my $job = $q->dequeue() )) {
         worker($job);
      }
   }    

   $q->enqueue(1..4, 1..4);

   $q->end();
   $_->join() for threads->list;
}