如何执行外部 Windows 命令并立即返回 Perl?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3928144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:24:34  来源:igfitidea点击:

How can I execute an external Windows command and instantly return in Perl?

windowsperl

提问by dferraro

I've tried using system() with fork(), tried exec(), and am still not getting what I need.

我试过将 system() 与 fork() 一起使用,试过 exec(),但仍然没有得到我需要的东西。

I want to write a Perl script which executes, let's say, a different Perl script five times in a row (sending it different parameter values), but I have it run concurrently. I realize I could turn my script into a .pm file and reference it, but I'd prefer to keep the child script independent of the parent...

我想编写一个 Perl 脚本,它可以连续五次执行不同的 Perl 脚本(向它发送不同的参数值),但我让它同时运行。我意识到我可以将我的脚本变成一个 .pm 文件并引用它,但我更愿意让子脚本独立于父脚本......

  • system() works, but executes the commands consecutively (makes sense per documentation)
  • exec() doesn't work - it only executes the first method (makes sense per doc)
  • I added a fork() to the child Perl script and then tried using system()
  • this did not work either.
  • backtick command ' documents says it works the same as system()...
  • system() 工作,但连续执行命令(每个文档都有意义)
  • exec() 不起作用 - 它只执行第一个方法(每个文档都有意义)
  • 我在子 Perl 脚本中添加了一个 fork(),然后尝试使用 system()
  • 这也不起作用。
  • 反引号命令'文档说它与 system() 的工作原理相同...

Isn't there a simple way in Perl (I'm using Windows XP) to execute a process, and not care about the return values or anything and just continue on into the next line of the parent script?

在 Perl(我使用的是 Windows XP)中是不是有一种简单的方法来执行一个进程,而不关心返回值或任何东西,而是继续进入父脚本的下一行?

回答by Eric Strom

You can do it like this (fork in the parent, exec in the child):

你可以这样做(在父级中分叉,在子级中执行):

for my $cmd qw(command1 command2 command3) {
    exec $cmd unless fork
}

The way that exec $cmd unless forkworks is that forkwill return a true value in the parent (the process id) and will return a false value in the child, thus exec $cmdonly gets run if forkreturns false (aka, in the child).

工作的方式exec $cmd unless forkfork将在父进程中返回一个真值(进程 ID)并在子进程中返回一个假值,因此exec $cmd只有在fork返回假(也就是在子进程中)时才会运行。

Or if you want to keep tabs on the process as it runs concurrently:

或者,如果您想在进程并发运行时密切关注它:

my @procs;

for my $cmd qw(cmd1 cmd2 cmd3) {

    open my $handle, '-|', $cmd or die $!;

    push @procs, $handle;
}

Then you can read from an element of @procsif you need to.

然后,@procs如果需要,您可以从 的元素中读取。

Or take a look at one of the many CPAN modules, like Forks::Superthat handle the details of fork management.

或者看看众多 CPAN 模块中的一个,比如Forks::Super处理分叉管理的细节。

回答by Tanktalus

On Windows, you can give the super-secret 1flag to the system, IIRC.

在 Windows 上,您可以向1系统 IIRC提供超级机密标志。

system 1, @cmd;

A Google search for this question on PerlMonks gives: Start an MS window in the background from a Perl script

在 PerlMonks 上对此问题的 Google 搜索给出了:从 Perl 脚本在后台启动 MS 窗口

回答by tster

A very lightweight approach.

一种非常轻量级的方法。

Windows:

视窗:

foreach my $cmd (@cmds)
{
    `start $cmd`;
}

Unix:

Unix:

foreach my $cmd (@cmds)
{
    `$cmd &`;
}

回答by Matthew Flaschen

You need to fork in the parent, and then exec in the new process. It goes like this, assuming A is the original script, and B is the one you want to do 5 times:

您需要在父进程中 fork,然后在新进程中执行。它是这样的,假设 A 是原始脚本,而 B 是您要执行 5 次的脚本:

                A1
fork in A1   -> A1 A2
exec B in A2 -> A1 B2
fork in A1   -> A1 A3 B2
exec B in A3 -> A1 B3 B2

etc.

等等。

回答by socket puppet

A module is overkill for this job. You want to forkto create a new process and then execto run a command in the new process. To run five commands, you need something like:

模块对于这项工作来说太过分了。您想fork创建一个新进程,然后exec在新进程中运行命令。要运行五个命令,您需要以下内容:

 for (my $i=0; $i<5; $i++) {
     if (fork() == 0) {
         exec($command[$i]);   # Runs command and doesn't return
     }
 }