Изменение в macOS Sierra предотвращает «скажем» быть exec’d в сценарии PHP

У меня есть MacOS-сервер с небольшим сайтом, который преобразует текстовые фрагменты в аудио, используя say команда.

С обновлением до Сьерры все прошло гладко, кроме одного: say команда не работает больше, когда обернута в exec() в моем сценарии PHP.

Страница просто перестает работать. Ошибка не обнаружена.

<?php
try {
exec('/usr/bin/say "hello"');
}
catch (Exception $e) { echo $e->getMessage(); }
?>

Обычно я сохраняю аудио фрагменты с say -o filename но я попробовал все варианты, а также другие команды оболочки, которые отлично работали, включая создание файлов в моей выходной папке.

Интересно, что если я запускаю его из командной строки, он работает — либо говорит громко, либо создает выходной файл.

macOS Sierra имеет PHP 5.6.24, поэтому я не думаю, что safe_mode применяется, верно?

Я хотел бы подчеркнуть, что изменения в PHP или команде say были относительно недавними, с новой ОС. Да, я посмотрел и попробовал другой вывод и перенаправление stderr, но скрипт просто зависает.

Видя say команда в Activity Viewer (графический интерфейс для top эквивалентно), я попытался попробовать это, не уверен, что это поможет:

2695 Thread_1742595   DispatchQueue_1: com.apple.main-thread  (serial)
+ 2695 start  (in libdyld.dylib) + 1  [0x7fffb0f58255]
+   2695 ???  (in say)  load address 0x10907d000 + 0x1fac  [0x10907efac]
+     2695 NewSpeechChannel  (in SpeechSynthesis) + 52  [0x7fff9acd3f19]
+       2695 SpeechChannelHandle::SpeechChannelHandle()  (in SpeechSynthesis) + 265  [0x7fff9acd797f]
+         2695 dispatch_once_f  (in libdispatch.dylib) + 38  [0x7fffb0f220e5]
+           2695 _dispatch_client_callout  (in libdispatch.dylib) + 8  [0x7fffb0f22128]
+             2695 ___ZN13SpeechGlobals8InstanceEv_block_invoke  (in SpeechSynthesis) + 28  [0x7fff9acd54da]
+               2695 SpeechGlobals::SpeechGlobals()  (in SpeechSynthesis) + 471  [0x7fff9acd56db]
+                 2695 xpc_connection_send_message_with_reply_sync  (in libxpc.dylib) + 154  [0x7fffb11b65a8]
+                   2695 dispatch_mach_send_with_result_and_wait_for_reply  (in libdispatch.dylib) + 45  [0x7fffb0f3cf39]
+                     2695 _dispatch_mach_send_and_wait_for_reply  (in libdispatch.dylib) + 591  [0x7fffb0f3cad4]
+                       2695 mach_msg  (in libsystem_kernel.dylib) + 55  [0x7fffb107e867]
+                         2695 mach_msg_trap  (in libsystem_kernel.dylib) + 10  [0x7fffb107f41a]
2695 Thread_1742600
2695 start_wqthread  (in libsystem_pthread.dylib) + 13  [0x7fffb116f211]
2695 _pthread_wqthread  (in libsystem_pthread.dylib) + 1426  [0x7fffb116f7b5]
2695 __workq_kernreturn  (in libsystem_kernel.dylib) + 10  [0x7fffb10874e6]

Это статистика:
Просмотр действий & gt; Статистика

И из открытых файлов и портов, я мог видеть, что я установил оба stdout а также stderr в /private/var/log/apache2/error_log пока там вообще ничего не видно.

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

<?php
try {
$pipes = array();
proc_close(proc_open("say hi", array(0 => array("pipe", "r"), 1 => array("pipe", "r"), 2 => array("pipe", "r")), $pipes, dirname(__FILE__), null));
} catch (Exception $e) { error_log($e->getMessage()); }
?>

ОБНОВЛЕНИЕ: Высокая Сьерра — то же самое.

ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ: после установки Mojave, которая удаляет большинство функций Server.app, я добавил MAMP для решения этой задачи. Услышьте это для себя, если вы хотите — это в macspeaks.com.

4

Решение

Я тоже испытал эту же проблему.

Вот обходной путь, который я только что придумал, но, честно говоря, я думаю, что это БОЛЬШОЙ СООБЩЕНИЕ, чтобы иметь возможность проигрывать аудио из php-скрипта на основе apache. У меня есть некоторые идеи о том, почему это может происходить, но после многих испытаний я, кажется, разрушаю свои собственные теории. Я думал, что это может быть связано с отсутствием активного TTY. Я не смог воспроизвести звук, запустив оболочку с sudo -iи МНОГИЕ МНОГИЕ другие attmepts из php, но я смог воспроизвести аудио, используя все те же команды с локального терминала, и, как оказалось, также через SSH в компьютер, так что это привело к моему последнему обходному пути , Еще раз, я думаю, что это WAY излишнее, но пока это единственный способ, которым я смог вернуть аудио в мои скрипты, основанные на php-технологиях (в основном связанные с гео-фехтованием).

Итак, мы идем, и да, я понимаю риски и тупость участвует в этом:

В моем скрипте php я создаю аудиофайл в каталоге / tmp с помощью команды, подобной этой:

exec "sudo -u <username> /usr/bin/say -o /tmp/outputfile.aiff --voice=Ava \"<What to Say>\"";

Затем, после того, как звуковой файл сгенерирован, я нашел единственный способ воспроизвести его (и фактически услышать вывод) из apache / php — использовать сценарий ожидающего, чтобы локально запустить ssh и воспроизвести его. Итак, моя следующая строка:

exec "sudo -u <username> -i ~<username>/expectscript";

Мой ожидаемый сценарий выглядит следующим образом:

#!/usr/bin/expect -f

spawn /usr/bin/ssh localhost
expect "Password"send "<PASSWORD>\r"expect "<username>"send "/usr/bin/afplay /tmp/outputfile.aiff\r"expect "<username>"send "/usr/bin/touch /tmp/touchthis\r"expect "<username>"send "exit\r"

Убедитесь, что вы заменили все <username> выше с вашим именем пользователя (без <> очевидно,) и <PASSWORD> с вашим паролем. Возможно, вам придется настроить сценарий ожидаемого, если ваши приглашения bash не содержат вашего имени пользователя, так как именно это я использовал в своем сценарии ожидания, чтобы найти возвращенное приглашение. Касание просто для того, чтобы определить, что ожидаемый сценарий сработал, и у вас есть ссылка на последний раз, когда файл был затронут.

Я надеюсь, что это открывает дискуссию о том, что на самом деле вызывает это, и мы можем найти более разумное решение. Я пробежал множество кроличьих норов, пытаясь найти разные способы заставить это работать, я создал приложения Automator и вызвал их из PHP (не работало). Я запускал оболочки внутри оболочек как мой пользователь, все выполнение команд всегда завершено успешно, просто нет звука. Все решения, которые я пробовал, будут нормально работать с терминала (и даже с php с терминала), но не с Apache / PHP.

0

Другие решения

Я испытал ту же проблему при использовании say командовать моей работой Дженкинс. Мой сервер Jenkins работает как демон на macOS Sierra.

В моем случае я решил эту проблему следующим образом:

  1. Войти как jenkins пользователь и сгенерируйте ключ ssh с ssh-keygen,
  2. присоединять ~/.ssh/id_rsa.pub в .ssh/authorized-keys так что пароль не будет запрошен.

    cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized-keys
    
  3. Измени мою работу Дженкинс, которая использует say команда как это:

    ssh localhost say -v Alex "Test"

Извините, я не тестировал с Apache / PHP, но почему бы вам не попробовать вот так:

<?php
try {
exec('/usr/bin/ssh localhost /usr/bin/say "hello"');
}
catch (Exception $e) { echo $e->getMessage(); }
?>
0

По вопросам рекламы [email protected]