Я хочу запустить скрипт из другого скрипта, использовать ту же версию perl и перенаправить ввод-вывод в текстовое поле, похожее на терминал
Я немного знаком с различными способами вызова сценария из другого. Мне не нужен обзор каждого из них, но у меня есть несколько вопросов. До этого, однако, я должен сказать вам, какова моя цель.
Я работаю над программой на perl/tk, которая: а) собирает информацию и помещает ее в хеш, и б) запускает другие сценарии, которые используют хэш информации, и некоторые аргументы командной строки. Каждый из этих других сценариев доступен в командной строке (с использованием другого сценария командной строки) и должен оставаться таким же. Поэтому я не могу просто поместить все это в модуль и назвать его хорошим. У меня есть полномочия изменять сценарии, но, опять же, они также должны использоваться в командной строке.
Текущий способ вызова другого скрипта - использование do, что означает, что я могу передать хеш и использовать ту же версию perl (я думаю). Но все STDOUT (и STDERR тоже, я думаю) идет в терминал.
Вот простой пример, чтобы продемонстрировать вывод:
this_thing.pl
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Tk;
my $mw = MainWindow->new;
my $button = $mw->Button(
-text => 'start other thing',
-command => \&start,
)->pack;
my $text = $mw->Text()->pack;
MainLoop;
sub start {
my $script_path = 'this_other_thing.pl';
if (not my $read = do $script_path) {
warn "couldn't parse $script_path: $@" if $@;
warn "couldn't do $script_path: $!" unless defined $read;
warn "couldn't run $script_path" unless $read;
}
}
this_other_thing.pl
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
print "Hello World!\n";
Как я могу перенаправить STDOUT и STDIN (для интерактивных сценариев, требующих ввода) в текстовое поле, используя метод do? Это вообще возможно?
Если я не могу использовать метод do, какой метод может перенаправить STDIN и STDOUT, а также разрешить передачу хэша и использование одной и той же версии perl?
Изменить: я разместил этот же вопрос в Perlmonks, по ссылке в первом комментарии. Пока что лучший ответ, похоже, использует модули, а дочерний скрипт просто является оберткой для модуля. Другие возможные решения: ICP::Run(3) и ICP в целом, Capture::Tiny и связанные модули и Tk::Filehandle. Было представлено решение, которое перенаправляет потоки вывода и ошибок, но, похоже, не влияет на поток ввода. Это также немного глупо и не рекомендуется.
Редактировать 2: Я публикую это здесь, потому что я пока не могу ответить на свой вопрос. Спасибо за ваши предложения и советы. Я пошел с предложением о Perlmonks. Было предложено превратить дочерние сценарии в модули и использовать сценарии-оболочки вокруг них для обычного использования. Тогда я просто смогу использовать модули, и весь код находится в одном месте. Это также гарантирует, что я не использую различные perl, я могу направить вывод из модуля куда угодно, и передача этого хеша теперь очень проста.
1 ответ
Чтобы перенаправить как STDIN, так и STDOUT подпроцесса, прочитайте раздел "Двунаправленная связь с другим процессом" на странице руководства perlipc: http://search.cpan.org/~rjbs/perl-5.18.1/pod/perlipc.pod#Bidirectional_Communication_with_Another_Process
Использование той же версии perl работает путем определения имени вашего интерпретатора perl и его явного вызова. $^X, вероятно, то, что вы хотите. Он может работать или не работать в разных операционных системах.
Передача хеша в подпроцесс не работает легко. Вы можете распечатать содержимое хеша в файл, а подпроцесс прочитать и проанализировать его. Вы можете уйти, не используя файл, используя канал STDIN между двумя процессами, или вы можете открыть отдельный канал () для этой цели. В любом случае, нельзя избежать печати и анализа данных при использовании подпроцессов, потому что два процесса используют два интерпретатора perl, каждый из которых имеет свое собственное пространство памяти и не может видеть переменные друг друга.
Вы можете избежать использования подпроцесса, используя fork() + eval() + require(). В этом случае отдельный интерпретатор perl не будет задействован, разветвленный интерпретатор унаследует всю память вашей программы со всеми переменными, дескрипторами открытых файлов, сокетами и т. Д., Включая передаваемый хеш. Однако я не вижу, откуда ваш второй Perl-скрипт мог получить свой хэш при запуске из CLI.