Изменение macOS Sierra предотвращает «say», чтобы быть exec'd в скрипте PHP

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

С обновлением до Sierra все прошло гладко, за исключением одного: команда 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 применяется, righht?

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

    Увидев команду say в Activity Viewer (GUI для 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] 

    Это статистика: Просмотр активности> Статистика

    И из открытых файлов и портов я мог видеть, что я устанавливаю как 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()); } ?> 

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

    Related of "Изменение macOS Sierra предотвращает «say», чтобы быть exec'd в скрипте PHP"

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

    Вот обход, который я только что придумал, но, честно говоря, я думаю, что это БОЛЬШАЯ МССА, чтобы иметь возможность воспроизводить аудио с php-скрипта на основе apache. У меня есть некоторые идеи о том, почему это может произойти, но при МНОГИХ тестах я, кажется, уничтожаю свои собственные теории. Я думал, что это могло быть связано с отсутствием активного TTY. Я не смог воспроизвести звук, запустив оболочку с помощью sudo -i и MANY MANY других attmepts от php, но я смог воспроизводить звук, используя все те же команды из локального терминала, и, как выясняется, также SSH «в компьютер, так что это привело к моей последней работе. Еще раз, я думаю, что это WAY overkill, но до сих пор это единственный способ, которым я смог вернуть аудио в свои веб-скрипты, основанные на 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.

    У меня возникла такая же проблема, когда я использовал команду say на моей работе Jenkins. Мой сервер Jenkins работает как демон на macOS Sierra.

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

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

       cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized-keys 
    3. Измените мою работу Jenkins, которая использует команду 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(); } ?>