Как запустить скрипт и не ждать его в Perl?

у меня есть системный вызов в Perl, который выглядит так:

system('/path/to/utility >> /redirect/to/log file');

но это ждет utility завершить. Я просто хочу запустить это и позволить скрипту Perl закончить независимо от того, является ли utility вызов завершен или нет.

как я могу это сделать?

Я попытался изменить строку на

system('/path/to/utility >> /redirect/to/log file &');

но этот синтаксис все еще ждет завершения вызова в Windows. Мне нужно заставить его работать как на Linux, так и на Windows.

4 ответов


if ($^O eq 'MSWin32') {
   system('start "" \path\to\utility >> \redirect\to\log_file');
} else {
   system('/path/to/utility >> /redirect/to/log_file &');
}

или

if ($^O eq 'MSWin32') {
   system(1, '\path\to\utility >> \redirect\to\log_file');
} else {
   system('/path/to/utility >> /redirect/to/log_file &');
}

вы можете попробовать посмотреть на fork ключевое слово и запустите системную команду из раздвоенного процесса. Вижу perlipc manpage для примеров.


эта общая задача была абстрагирована в модуль CPAN Proc::Background


самый простой способ в POSIX-подобных системах-это тот, который вы уже пробовали:

system('/path/to/utility >> /redirect/to/log_file &');

самый простой способ получить инструмент для выполнения в фоновом режиме в Windows используется start.exe в качестве помощника запуска:

system('start /path/to/utility >> /redirect/to/log_file');

однако я не знаю, работает ли он для перенаправления вывода в файл журнала таким образом, и у меня нет системы Windows в этот самый момент для его тестирования.

Да, это означает, что вам понадобится ветвь кода в зависимости от текущей системы, но другие решения тоже. Если ваш Perl имеет fork() эмуляция, вы можете фактически использовать fork() в обеих системах (это немного сложнее, так как вы не можете перенаправить stdout в файл журнала, который легко, вы сначала должны открыть его в Perl и сделать его stdout раздвоенного ребенка перед вызовом нового процесса). Если ваш Windows Perl не имеет fork() эмуляция, вам также нужна ветвь кода, так как в этом случае вы можете использовать fork() только в UNIX, и вам нужно будет использовать Win32::Process::Create С DETACHED_PROCESS вариант на Windows.

но, возможно, вы можете сначала сообщить нам, если использование start уже работает для вас. Если нет, может быть start.exe не обрабатывает слеши. В этом случае вам, возможно, придется использовать что-то вроде

C:\path\to\utility

вместо этого (важна двойная обратная косая черта! Одна обратная косая черта имеет особое значение в строковых литералах; это escape-символ).

чтобы узнать, работаете ли вы в Windows или нет, взгляните на переменную $OSNAME или $^OS, он должен сказать что-то вроде "MSWin32" на Windows.