Как сохранить переменные среды между двумя вызовами для открытия? - PullRequest
4 голосов
/ 12 февраля 2020

У меня perl код работает на Windows. Этот код дважды вызывает 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);

Мой set.bat файл, который устанавливает переменную среды:

set VAR=20
echo %VAR%

И мой get.bat, который использует переменную окружения:

echo %VAR%

Когда я запускаю код perl, вот результаты:

>perl my_code.pl
>set VAR=20
>echo 20
20
>echo
ECHO is on.

Мы видим, что set.bat правильно устанавливает значение VAR, но get.bat не может его использовать.


Кроме того, если я запускаю два моих пакетных сценария подряд из cmd подскажите, у меня есть ожидаемый результат:

>set.bat
>set VAR=20
>echo 20
20
>get.bat
>echo 20
20

Что я могу сделать, чтобы мой второй пакетный скрипт использовал мою переменную окружения в моем perl коде?

Ответы [ 3 ]

7 голосов
/ 12 февраля 2020

open с конвейером создает новый процесс , а затем ваш set.bat запускается в этом процессе и устанавливает эту переменную среды в этого процесса , который затем завершается.

Затем get.bat работает в другом процессе и ничего не видит в первом процессе.

Однако они оба наследуют среду процесса, в котором выполняется ваш скрипт Perl. Таким образом, вы можете установить необходимую среду в скрипте (например, через %ENV), а затем создать подпроцесс, а затем этот подпроцесс увидит среду.

С другой стороны, вы можете запустить оба сценария оболочки в одном и том же подпроцессе, если это соответствует вашим целям, например, через system. Затем можно export изменить переменную в среде, и после ее source -дедания ее увидит следующий запущенный скрипт. Вот пример в Linux (прямо сейчас не могу Windows).

Программа командной строки ("one-liner")

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

с файлом set.bat.sh

#!/bin/bash
VAR=20
export VAR

и файл get.bat.sh

#!/bin/bash
echo $VAR

Однострочник печатает одну строку с 20.


Канал - open обычно называется fork процессом (см. open ), но на Windows, который может быть эмулирован (только через потоки), так как нет собственного fork; см. perlfork . Однако perlport указывает, что в Windows pipe- open создает подпроцесс (через Win32 API).


A Linux пример (не могу проверить в Windows сейчас)

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

с set.bat.sh файлом

#!/bin/bash
VAR=20
echo $VAR

и get.bat.sh

#!/bin/bash
echo $VAR

Поскольку подпроцесс не может напрямую изменить среду своего родителя, set.bat.sh печатает $VAR до STDOUT, а затем его родитель, скрипт perl, может прочитать его из этого потока (захваченный qx) и установить его в его собственном окружении, которое наследует его следующий (великий) ребенок get.bat.sh. (A system разветвляет процесс, и в нем разветвляется другой процесс для запуска get.bat.sh. Среда передается.)

Слабость этого, конечно, заключается в том, что сценарий perl нуждается в чтобы узнать имя переменной, VAR. В этом случае set.bat улучшит отправку самого имени вместе со значением.

2 голосов
/ 12 февраля 2020

Это нелегко сделать. Причина в том, что дочерний процесс обычно наследует копию среды родительского процесса. Включая переменные окружения.

См .: Как использовать переменные ENV среди Perl Скриптов

2 голосов
/ 12 февраля 2020

Подпроцессы изолированы друг от друга и, как правило, не могут влиять на окружение друг друга или родительского процесса.

Для этого ограниченного примера, может быть, достаточно переопределить часть языка CMD в Perl. Если вам нужно поддерживать только небольшое подмножество, например, например, присваивать переменные строки stati c, это не так уж сложно:

if ($line ~ /^set\s+(\w+)=(\w+)$/) {
    $ENV{$1} = $2;
}

Возможно, используйте другое значение ha sh, чем ENV если вам абсолютно не нужно распространять эти значения в среде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...