我有几个测试脚本,每个脚本都运行一个测试 PHP 应用程序。每个脚本都会永远运行。
因此,、cat.sh
和dog.sh
分别foo.sh
运行一个 PHP 脚本。每个 shell 脚本都会循环运行 PHP 应用程序,因此它会一直运行,每次运行后都会进入休眠状态。
我正在尝试弄清楚如何同时并行运行脚本。在 stdout/term 窗口中查看 PHP 应用程序的输出。
我认为,做如下的事情可能会有效:
foo.sh > &2
dog.sh > &2
cat.sh > &2
在 shell 脚本中这已经足够了,但是它不起作用。
foo.sh, runs foo.php once, and it runs correctly
dog.sh, runs dog.php in a never ending loop. it runs as expected
cat.sh, runs cat.php in a never ending loop
*** this never runs!!!
看来 shell 脚本永远无法运行cat.sh
。如果我cat.sh
在单独的窗口/术语中自行运行,它会按预期运行。
有人知道如何让这些脚本并行运行吗?
答案1
您当前的设置是按顺序运行命令。第一个运行,并完成,允许第二个开始。第二个永远不会结束,所以第三个永远没有机会开始。
尝试这个:
foo.sh >foo.out 2>foo.err &
dog.sh >dog.out 2>dog.err &
cat.sh >cat.out 2>cat.err &
这将告诉每个命令在后台运行,并将其输出和错误信息发送到文件。当命令在后台运行时,它会脱离当前会话,并允许下一个命令运行。将“与”符号 ( &
) 放在行的最后一个字符很重要。否则,可能无法正确识别它。
或者,让每个 shell 脚本运行.php
您显然使用与上述相同的语义调用的关联脚本。在这种情况下,您的脚本foo.sh
可能包含:
#!/bin/bash
php foo.php >foo.out 2>foo.err &
最后,如果您需要真正的并行操作,请查看GNU 并行。
注意:如果您确实希望输出到屏幕/终端,则可以关闭输出重定向:
foo.sh &
但是请记住,同时运行多个命令可能会导致混乱的输出(您现在可能知道哪个命令产生了什么输出或错误),并且如果您注销,输出就无处可去。
答案2
这可以通过并行命令完成。
美丽的例子:平行线
[me@neo]<bash><~> 19
05:51 Tue Mar 05 > man -f parallel
parallel (1) - run programs in parallel
--
parallel -j 3 -- "sh foo.sh" "sh dog.sh" "sh cat.sh"
这将同时并行启动 3 个脚本。
parallel sh -c "echo hi; sleep 2; echo bye" -- 1 2 3
这将默认启动相同命令的多个进程,具体取决于 CPU 数量。
parallel -j 3 sh -c "echo hi; sleep 2; echo bye" -- 1 2 3
这将强制同时执行 3 个进程,即使您只有 2 个 CPU。
例子:
[me@neo]<bash><~> 31
06:09 Tue Mar 05 > parallel -j 10 sh -c "echo Hello World; sleep 3; echo Good morning" -- $(seq 1 10)
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
答案3
Chris 对大多数脚本都有一个很好的总体想法:每个命令都以 结尾,&
它们就会进入后台。话虽如此,这是我为一些高端任务保留的东西。让我向你介绍我的方便的工具箱脚本,parallel-exec.pl
#!/usr/bin/perl
use threads;
use Thread::Queue;
my @workers;
my $num_threads = shift;
my $dbname = shift;
my $queue = new Thread::Queue;
for (0..$num_threads-1) {
$workers[$_] = new threads(\&worker);
print "TEST!\n";
}
while ($_ = shift @ARGV) {
$queue->enqueue($_);
}
sub worker() {
while ($file = $queue->dequeue) {
system ('./parser.pl', $dbname, $file);
}
}
for (0..$num_threads-1) { $queue->enqueue(undef); }
for (0..$num_threads-1) { $workers[$_]->join; }
通过一些轻微的调整,您可以更改线程数、提供命令数组等。就目前情况而言,它需要命令行上指定的线程数、数据库名称和要导入的文件列表,然后为每个文件生成一个实例,同时运行指定的数量。
答案4
尝试这个:
./Cat.sh &
./Dog.sh &
./foo.sh &
它们将在后台运行。
为了更好地控制进程,可以使用多处理模块将它们嵌入到 Python 脚本中
import multiprocessing as mp
import os
def Run(script_name):
os.system('./'+script _name+'.sh)
Pool=[]
For s in [your script list]:
p=mp.Process(target =Run ,args=(s,))
Pool.append(p)
For p in P:
p.start()
Fort p in P:
p.join()