Spawn Expect из потока perl

Я работаю над сценарием, который должен периодически запускать процесс Expect (каждые 5 минут), чтобы выполнить некоторую работу. Ниже приведен код, который у меня есть, который порождает процесс Expect и выполняет некоторую работу. Основной процесс скрипта все время выполняет какую-то другую работу, например, он может ожидать ввода данных пользователем, из-за этого я вызываю эту функцию spawn_expect в потоке, который продолжает вызывать ее каждые 5 минут, но проблема в том, что Expect не работает должным образом.

Однако, если я заменю поток другим процессом, то есть если я разветвлю и позволю одному процессу позаботиться о порождении Expect, а другой процесс сделает основную работу сценария (например, ожидая приглашения), тогда Expect работает нормально.

Мой вопрос в том, возможно ли запустить процесс ожидания потока? я должен прибегнуть к использованию процесса для выполнения этой работы? Спасибо !

sub spawn_expect {
    my $expect = Expect->spawn($release_config{kinit_exec});
    my $position = $expect->expect(10,
                    [qr/Password.*: /, sub {my $fh = shift; print $fh "password\n";}],
                    [timeout => sub {print "Timed out";}]);
    # if this function is run via a process, $position is defined, if it is run via a thread, it is not defined                         
    ...
 }

person comatose    schedule 09.05.2017    source источник
comment
Можете ли вы уточнить: почему это должно проходить через потоки? (Какова цель -- вы собираетесь что-то делать с $position в другом потоке?) Что значит не определено -- в другом потоке?   -  person zdim    schedule 09.05.2017
comment
@zdim Причина, по которой это должно проходить через потоки или другой отдельный процесс, заключается в том, что я хочу, чтобы основной процесс выполнял какую-то другую работу, включая получение ввода от пользователя и выполнение некоторых других действий, поэтому мне нужно, чтобы он всегда реагировал на ввод. Это вынуждает меня использовать отдельный поток/процесс для периодической работы с Expect. Под $position не определено то, что я имею в виду, что Expect не соответствует паролю. Он не используется никаким другим потоком (в основном это цикл обновления kinit, который предоставляет пароль через ожидание очень периодического интервала)   -  person comatose    schedule 09.05.2017
comment
Спасибо. Итак, вы можете красиво fork покончить с этим, но остается вопрос, почему Expect не выполняет свою работу в потоке.   -  person zdim    schedule 09.05.2017


Ответы (1)


Создайте объект Expect заранее (не внутри потока) и передать его в поток

my $exp = Expect->spawn( ... );
$exp->raw_pty(1);
$exp->log_stdout(0);

my ($thr) = threads->create(\&login, $exp);
my @res = $thr->join();    
# ...

sub login {
    my $exp = shift;
    my $position = $exp->expect( ... );
    # ...
}

Я тестировал с несколькими потоками, где один использует Expect с пользовательским тестовым скриптом и возвращает вывод скрипта в основной поток. Дайте мне знать, если я должен опубликовать эти (короткие) программы.

Когда объект Expect создается внутри потока, у меня тоже происходит сбой. Я предполагаю, что в этом случае он не сможет настроить свой pty так, как обычно.

Однако, учитывая пояснение в комментарии, я бы использовал fork для этой работы.

person zdim    schedule 09.05.2017