如何在两次 open 调用之间保持环境变量?

Pie*_*rre 4 perl batch-file

我有一个在 Windows 上运行的 perl 代码。此代码调用open两次以执行两个不同的批处理文件。第一个设置环境变量,第二个需要使用它。不幸的是,设置为变量的值在两次调用之间丢失了。

这是我的 Perl 代码。

my $hdl;
open($hdl, "set.bat |");
while(my $line = <$hdl>) {
    print("$line\n");
}
close($hdl);

open($hdl, "get.bat |");
while(my $line = <$hdl>) {
    print("$line\n");
}
close($hdl);
Run Code Online (Sandbox Code Playgroud)

set.bat设置环境变量的文件:

set VAR=20
echo %VAR%
Run Code Online (Sandbox Code Playgroud)

而 myget.bat使用环境变量:

echo %VAR%
Run Code Online (Sandbox Code Playgroud)

当我运行 perl 代码时,结果如下:

>perl my_code.pl
>set VAR=20
>echo 20
20
>echo
ECHO is on.
Run Code Online (Sandbox Code Playgroud)

我们可以看到set.bat正确设置了 的值VARget.bat无法使用它。


此外,如果我从cmd提示中连续运行我的两个批处理脚本,我会得到我期望的结果:

>set.bat
>set VAR=20
>echo 20
20
>get.bat
>echo 20
20
Run Code Online (Sandbox Code Playgroud)

我该怎么做才能让我的第二个批处理脚本在我的 perl 代码中使用我的环境变量?

zdi*_*dim 7

open与管道创建一个新进程,然后你set.bat在这个过程中运行,并且设置环境变量在这一进程,然后退出。

然后get.bat在另一个不同的进程中运行,并且看不到第一个进程的任何内容。

但是,它们都继承了运行 Perl 脚本的进程的环境。因此,您可以在脚本中设置所需的环境(%ENV例如通过),然后创建一个子进程,然后该子进程看到该环境。

另一方面,您可以在同一个子进程中运行两个 shell 脚本,如果这符合您的目的,system例如通过。然后可以将export一个变量放入环境中,在它被source-ed 之后,下一个要运行的脚本将看到它。这是 Linux 中的一个例子(现在不能做 Windows)。

一个命令行程序(“one-liner”)

perl -we'system("/bin/bash", "-c", q(source set.bat.sh; get.bat.sh))'
Run Code Online (Sandbox Code Playgroud)

与文件 set.bat.sh

#!/bin/bash
VAR=20
export VAR
Run Code Online (Sandbox Code Playgroud)

和文件 get.bat.sh

#!/bin/bash
echo $VAR
Run Code Online (Sandbox Code Playgroud)

单行打印一行20


pipe-open通常被fork称为进程(参见open),但在 Windows 上只能模拟(通过线程),因为没有 native fork;见perlfork。但是,perlport表明在 Windows 上,管道open确实创建了一个子进程(通过 Win32 API)。


一个 Linux 示例(目前无法在 Windows 中测试)

perl -we'$v = qx("set.bat.sh"); chomp $v; $ENV{VAR} = $v; system("get.bat.sh")'
Run Code Online (Sandbox Code Playgroud)

set.bat.sh文件

#!/bin/bash
VAR=20
echo $VAR
Run Code Online (Sandbox Code Playgroud)

get.bat.sh

#!/bin/bash
echo $VAR
Run Code Online (Sandbox Code Playgroud)

由于子进程不能直接其父的环境改变set.bat.sh打印$VARSTDOUT,然后它的父,Perl脚本,可以从流(由捕获阅读qx),把它在自己的环境,它的下一个(grand-)子get.bat.sh继承. (一个systemfork 一个进程,并在其中 fork 另一个进程运行get.bat.sh。环境被传递。)

当然,这样做的弱点是 perl 脚本需要知道变量的名称VAR. 一个改进是set.bat将名称本身与值一起发送。