form1.cn
Make a little progress every day

web执行php调用exec(unoconv)命令失败解决方案

05th of March 2021 PHP Laravel 2210

本人环境是:

nginx + php-fpm


创建PHP文件如下:

<?php
exec('unoconv -f pdf /home/test.pptx', $res, $rc);
print($rc);
// /home/test.pptx  是我的测试文件
// exec有3个参数,第一个是要执行的命令,第二个是参数是一个数组,数组的值是由第一个命令执行后生成的,第三个参数执行的状态,0表示成功,其他都表示失败。


将该文件上传服务器通过web中的url进行访问后,打印exec的第三个参数rc为1,说明命令执行失败,但确不知道原因


将代码更改如下:

<?php
exec('unoconv -f pdf /home/test.pptx 2>&1', $res, $rc);
print($rc);
print($res);

使用 2>&1, 命令就会输出shell执行时的错误到$res变量, 输出该变量即可分析。


在次运行后,得到命令错误信息:

0: "Traceback (most recent call last):"
1: "  File "/usr/bin/unoconv", line 1205, in <module>"
2: "    run()"
3: "  File "/usr/bin/unoconv", line 1115, in run"
4: "    office_environ(of)"
5: "  File "/usr/bin/unoconv", line 202, in office_environ"
6: "    os.environ['PATH'] = realpath(office.basepath, 'program') + os.pathsep + os.environ['PATH']"
7: "  File "/usr/lib64/python2.7/UserDict.py", line 23, in __getitem__"
8: "    raise KeyError(key)"
9: "KeyError: 'PATH'"


这他niang是什么东西,貌似是python代码出错,最后有一个  "KeyError: 'PATH'"


此时在网上找了很多解决方案,尝试无果,尝试如下:

1,/usr/bin/unoconv 的执行权限改为777

2, /run/user/0/dconf   /run/user权限更改了 777

3, /ect/sudoers 增加了 :  www ALL=(ALL) NOPASSWD: ALL

4,还更改了测试pptx文件权限为777

以上尝试全部无果


最后在 github 上面找到一提问,从提问的回答中找到解决方案:

网页地址:https://github.com/dagwieers/unoconv/issues/87#issuecomment-18800070%29

回答信息:

centos 7.3 nginx with php via php-fpm, the env in php is cleaned by php-fpm
u can use putenv to set evn["PATH"] in php code, examples
putenv("PATH=/sbin:/bin:/usr/sbin:/usr/bin"); 
var_dump(shell_exec('unoconv -vvvv -f pdf -o 123.pdf 123.doc));
or u can set env use one line shell cmd
var_dump(shell_exec('PATH=/sbin:/bin:/usr/sbin:/usr/bin'.' unoconv -vvvv -f pdf -o 123.pdf 123.doc));
or u can change php-fpm.d/www.conf to pass the env to php, add this line
clean_env = no
and the restart php-fpm
systemctl restart php-fpm.service

发现和我的环境与问题是一致的,于是开始尝试

<?php
exec('PATH=/sbin:/bin:/usr/sbin:/usr/bin unoconv -f pdf /home/test.pptx 2>&1', $res, $rc);
print($rc);
print($res);


在次运行发现转换成功