Jos*_*abr 5 php exec macos-sierra
我有一台有一个小站点的macOS服务器,该站点使用say命令将文本片段转换为音频。
升级到Sierra后,除了一件事情外,一切都变得顺利了:将say命令包装exec()到我的PHP脚本中后,该命令不再起作用。
页面刚刚超时。也没有发现错误。
<?php
try {
exec('/usr/bin/say "hello"');
}
catch (Exception $e) { echo $e->getMessage(); }
?>
Run Code Online (Sandbox Code Playgroud)
通常,我会用它们保存音频片段,say -o filename但我尝试了所有变体以及其他运行良好的shell命令,包括在输出文件夹中创建文件。
有趣的是,如果我从命令行运行它,则可以正常工作-大声说出来或创建一个输出文件。
macOS Sierra具有PHP 5.6.24,所以我认为safe_mode不适用,对吗?
我想强调一下,在新操作系统中,PHP或say命令的更改是最近的。是的,我确实调查过并尝试了不同的输出和stderr重定向,但是脚本只是挂起了。
say在Activity Viewer(top等效于GUI )中看到命令后,我尝试对其进行采样,不确定是否有帮助:
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]
Run Code Online (Sandbox Code Playgroud)
而从打开的文件和港口,我看得出来,我都设置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()); }
?>
Run Code Online (Sandbox Code Playgroud)
更新:高塞拉山脉是相同的。
最终更新:安装Mojave(删除了大部分Server.app功能)后,我添加了MAMP来处理此任务。听到它自己,如果你想-这是在macspeaks.com。
故事继续:在安装Catalina的过程中,还是MAMP更新了?(现在是5.5版),我再次杀死了它。叹...
小智 0
我也经历过同样的问题。
这是我刚刚想出的一个解决方法,但老实说,我认为仅仅能够从基于 apache 的 php 脚本播放音频就很混乱。我对为什么会发生这种情况有一些想法,但经过多次测试,我似乎破坏了自己的理论。我认为这可能与没有活跃的 TTY 有关。我无法通过启动 shell 以及sudo -i来自 php 的许多其他尝试来播放音频,但我能够使用本地终端中的所有相同命令来播放音频,事实证明,也可以通过 SSH 来播放音频计算机,所以这导致了我最新的解决方法。再一次,我认为这太过分了,但到目前为止,这是我能够在基于 Web 的 php 驱动脚本(主要与地理围栏相关)中恢复音频的唯一方法。
所以,我们开始吧,是的,我理解其中涉及的风险和愚蠢:
在我的 php 脚本中,我使用类似于以下的命令在 /tmp 目录中生成一个音频文件:
exec "sudo -u <username> /usr/bin/say -o /tmp/outputfile.aiff --voice=Ava \"<What to Say>\"";
Run Code Online (Sandbox Code Playgroud)
然后,在生成音频文件后,我发现从 apache/php 播放它(并实际听到输出)的唯一方法是使用 Expect 脚本在本地进行 ssh 并播放它。所以我的下一行是:
exec "sudo -u <username> -i ~<username>/expectscript";
Run Code Online (Sandbox Code Playgroud)
我的期望脚本如下:
#!/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"
Run Code Online (Sandbox Code Playgroud)
确保将<username>上述所有内容替换为您的用户名(显然没有<>)和<PASSWORD>密码。如果您的 bash 提示不包含您的用户名,您可能需要调整 Expect 脚本,因为这是我在 Expect 脚本中使用的内容来查找返回的提示。触摸只是为了确定期望脚本是否有效,并且您可以参考上次触摸文件的时间。
我希望这能引发对实际原因的讨论,以便我们能够确定更合理的解决方案。我陷入了很多困境,试图找到不同的方法来让它工作,我创建了 Automator 应用程序并从 PHP 调用这些应用程序(不起作用。)我以我的用户身份在 shell 中启动了 shell,所有命令的执行总是成功完成,只是没有音频输出。我尝试过的所有解决方案都可以从终端(甚至从终端的 php)正常工作,只是不能从 Apache/PHP 工作。