我正在使用Thread::Pool::Simple创建一些工作线程。每个工作线程都会做一些事情,包括先调用chdir,然后执行外部Perl脚本(如果重要的话,可以从jbrowse基因组浏览器执行)。我使用capturex来调用外部脚本,并在其失败时终止。
我发现当我使用超过一个线程时,事情开始变得混乱。经过一番研究之后。看起来有些线程的当前目录不正确。
也许chdir在线程之间传播(即不是线程安全的)?或者可能是capturex的问题
那么,如何安全地为每个线程设置工作目录呢?
**更新**
按照在执行时更改目录的建议,我想问一下到底应该如何将这两个命令传递给capturex
目前我有:
my @args = ( "bin/flatfile-to-json.pl", "--gff=$gff_file", "--tracklabel=$track_label", "--key=$key", @optional_args );
capturex( [0], @args );如何向@args添加另一个命令?capturex会继续死于任何命令的错误吗?
发布于 2010-09-19 19:17:56
我认为你可以很容易地解决你的“在运行命令之前如何在孩子中修改”的问题,通过放弃IPC::System::Simple作为不适合这项工作的工具。
而不是做
my $output = capturex($cmd, @args);做一些类似的事情:
use autodie qw(open close);
my $pid = open my $fh, '-|';
unless ($pid) { # this is the child
chdir($wherever);
exec($cmd, @args) or exit 255;
}
my $output = do { local $/; <$fh> };
# If child exited with error or couldn't be run, the exception will
# be raised here (via autodie; feel free to replace it with
# your own handling)
close ($fh);如果您从capturex获得的是行的列表,而不是标量输出,那么唯一需要更改的就是倒数第二行(到my @output = <$fh>;)。
有关forking-open的更多信息,请访问perldoc perlipc。
与capture("chdir wherever ; $cmd @args")相比,这样做的好处是它不会让shell有机会对您的@args做坏事。
更新代码(不捕获输出)
my $pid = fork;
die "Couldn't fork: $!" unless defined $pid;
unless ($pid) { # this is the child
chdir($wherever);
open STDOUT, ">/dev/null"; # optional: silence subprocess output
open STDERR, ">/dev/null"; # even more optional
exec($cmd, @args) or exit 255;
}
wait;
die "Child error $?" if $?;发布于 2010-09-19 16:46:38
我不认为“当前工作目录”是每个线程的属性。我希望它是这个过程的一个属性。
不过,我们还不清楚为什么需要使用chdir。您是否可以不启动外部脚本来适当地设置新进程的工作目录?这听起来是一种更可行的方法。
https://stackoverflow.com/questions/3745048
复制相似问题