1、上传选题素材时,服务器内部错误。如图1
{ "name": "Internal Server Error", "message": "服务器内部错误。", "code": 0, "status": 500 }
2、决定调整为开发模式 (dev),再次上传选题素材,以查看更为详细的错误信息,报错:chmod(): Operation not permitted,如图2
{ "name": "Exception", "message": "Failed to change permissions for directory /"/webtv/wangjie/pcs-api/tmp/2019/12/05/": chmod(): Operation not permitted", "code": 2, "type": "yii//base//Exception", "file": "/mcloud/www/pcs-api/vendor/yiisoft/yii2/helpers/BaseFileHelper.php", "line": 635, "stack-trace": [ "#0 /mcloud/www/pcs-api/common/services/AssetService.php(77): yii//helpers//BaseFileHelper::createDirectory('/webtv/wangjie/...')", "#1 /mcloud/www/pcs-api/api/rests/asset/UploadAction.php(93): common//services//AssetService::uploadTempAssets(Array)", "#2 [internal function]: api//rests//asset//UploadAction->run()", "#3 /mcloud/www/pcs-api/vendor/yiisoft/yii2/base/Action.php(94): call_user_func_array(Array, Array)", "#4 /mcloud/www/pcs-api/vendor/yiisoft/yii2/base/Controller.php(157): yii//base//Action->runWithParams(Array)", "#5 /mcloud/www/pcs-api/vendor/yiisoft/yii2/base/Module.php(528): yii//base//Controller->runAction('upload', Array)", "#6 /mcloud/www/pcs-api/vendor/yiisoft/yii2/web/Application.php(103): yii//base//Module->runAction('v1/asset/upload', Array)", "#7 /mcloud/www/pcs-api/vendor/yiisoft/yii2/base/Application.php(386): yii//web//Application->handleRequest(Object(yii//web//Request))", "#8 /mcloud/www/pcs-api/api/web/index.php(17): yii//base//Application->run()", "#9 {main}" ], "previous": { "name": "PHP Warning", "message": "chmod(): Operation not permitted", "code": 2, "type": "yii//base//ErrorException", "file": "/mcloud/www/pcs-api/vendor/yiisoft/yii2/helpers/BaseFileHelper.php", "line": 633, "stack-trace": [ "#0 [internal function]: yii//base//ErrorHandler->handleError(2, 'chmod(): Operat...', '/mcloud/www/pcs...', 633, Array)", "#1 /mcloud/www/pcs-api/vendor/yiisoft/yii2/helpers/BaseFileHelper.php(633): chmod('/webtv/wangjie/...', 509)", "#2 /mcloud/www/pcs-api/common/services/AssetService.php(77): yii//helpers//BaseFileHelper::createDirectory('/webtv/wangjie/...')", "#3 /mcloud/www/pcs-api/api/rests/asset/UploadAction.php(93): common//services//AssetService::uploadTempAssets(Array)", "#4 [internal function]: api//rests//asset//UploadAction->run()", "#5 /mcloud/www/pcs-api/vendor/yiisoft/yii2/base/Action.php(94): call_user_func_array(Array, Array)", "#6 /mcloud/www/pcs-api/vendor/yiisoft/yii2/base/Controller.php(157): yii//base//Action->runWithParams(Array)", "#7 /mcloud/www/pcs-api/vendor/yiisoft/yii2/base/Module.php(528): yii//base//Controller->runAction('upload', Array)", "#8 /mcloud/www/pcs-api/vendor/yiisoft/yii2/web/Application.php(103): yii//base//Module->runAction('v1/asset/upload', Array)", "#9 /mcloud/www/pcs-api/vendor/yiisoft/yii2/base/Application.php(386): yii//web//Application->handleRequest(Object(yii//web//Request))", "#10 /mcloud/www/pcs-api/api/web/index.php(17): yii//base//Application->run()", "#11 {main}" ] } }
3、查看挂载的目录,/webtv/wangjie/pcs-api/tmp/2019/12/05,连接上传了 2 次,第 1 次生成了目录:12,第 2 次生成了目录:05,如图3
[root@d48dedd9fceb pcs-api]# ls 2019 tmp [root@d48dedd9fceb pcs-api]# cd tmp [root@d48dedd9fceb tmp]# ls 2019 [root@d48dedd9fceb tmp]# cd 2019 [root@d48dedd9fceb 2019]# ls 10 11 12 [root@d48dedd9fceb 2019]# cd 12 [root@d48dedd9fceb 12]# ls 05 [root@d48dedd9fceb 12]# cd 05 [root@d48dedd9fceb 05]# ls [root@d48dedd9fceb 05]# pwd /webtv/wangjie/pcs-api/tmp/2019/12/05 [root@d48dedd9fceb 05]# ls -l total 0 [root@d48dedd9fceb 05]# cd .. [root@d48dedd9fceb 12]# ls -l total 0 drwxrwxrwx 2 root root 0 Dec 5 15:28 05 [root@d48dedd9fceb 12]#
4、分析原因,当前用户 为 nginx ,在开发环境中查看目录 的用户,而在报错的环境中,目录的用户为 root,且模式为 0777,当前用户指的是执行 PHP 的用户。很可能和通常的 shell 或者 FTP 用户不是同一个。在大多数系统下文件模式只能被文件所有者的用户改变。如图4
[root@685b4b7fd197 /]# cd /webtv/wangjiedev/pcs-api/ [root@685b4b7fd197 pcs-api]# ls 2019 php-fpm1.conf php-fpm.conf tmp [root@685b4b7fd197 pcs-api]# cd tmp [root@685b4b7fd197 tmp]# ls -l total 0 drwxrwxr-x 9 nginx nginx 101 Dec 2 16:26 2019
5、最终决定继续类:yii/helpers/FileHelper,覆写静态方法:createDirectory($path, $mode = 0775, $recursive = true),当 chmod() 改变文件模式失败后,返回 true,不抛出异常,继续后续的执行,新建类:/common/helpers/FileHelper.php
<?php /** * Created by PhpStorm. * User: Qiang Wang * Date: 2019/12/05 * Time: 16:45 */ namespace common/helpers; /** * File system helper. * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class FileHelper extends /yii/helpers/FileHelper { /** * Creates a new directory. * * This method is similar to the PHP `mkdir()` function except that * it uses `chmod()` to set the permission of the created directory * in order to avoid the impact of the `umask` setting. * * @param string $path path of the directory to be created. * @param int $mode the permission to be set for the created directory. * @param bool $recursive whether to create parent directories if they do not exist. * @return bool whether the directory is created successfully * @throws /yii/base/Exception if the directory could not be created (i.e. php error due to parallel changes) */ public static function createDirectory($path, $mode = 0775, $recursive = true) { if (is_dir($path)) { return true; } $parentDir = dirname($path); // recurse if parent dir does not exist and we are not at the root of the file system. if ($recursive && !is_dir($parentDir) && $parentDir !== $path) { static::createDirectory($parentDir, $mode, true); } try { if (!mkdir($path, $mode)) { return false; } } catch (/Exception $e) { if (!is_dir($path)) {// https://github.com/yiisoft/yii2/issues/9288 throw new /yii/base/Exception("Failed to create directory /"$path/": " . $e->getMessage(), $e->getCode(), $e); } } try { return @chmod($path, $mode); } catch (/Exception $e) { throw new /yii/base/Exception("Failed to change permissions for directory /"$path/": " . $e->getMessage(), $e->getCode(), $e); } } }
6、后续创建目录时,皆引用新创建的类:common/helpers/FileHelper,进入报错的环境,手动删除目录:/webtv/wangjie/pcs-api/tmp/2019/12,如图5
7、再次上传选题素材,报错:”创建目录:/webtv/wangjie/pcs-api/tmp/2019/12/05,失败”,如图6
{ "name": "Internal Server Error", "message": "创建目录:/webtv/wangjie/pcs-api/tmp/2019/12/05,失败", "code": 202002, "status": 500, "type": "yii//web//ServerErrorHttpException" }
8、查看挂载的目录,/webtv/wangjie/pcs-api/tmp/2019/12/05,已经第 1 次就创建成功,已经确定不能够一次性创建多个目录的问题已经得到解决,如图7
9、分析原因在于,静态方法:createDirectory($path, $mode = 0775, $recursive = true),未返回 true,进而导致判断时,以为创建目录失败,抛出异常,因此,不论 chmod 结果如何,皆返回 true
<?php /** * Created by PhpStorm. * User: Qiang Wang * Date: 2019/12/05 * Time: 16:45 */ namespace common/helpers; /** * File system helper. * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class FileHelper extends /yii/helpers/FileHelper { /** * Creates a new directory. * * This method is similar to the PHP `mkdir()` function except that * it uses `chmod()` to set the permission of the created directory * in order to avoid the impact of the `umask` setting. * * @param string $path path of the directory to be created. * @param int $mode the permission to be set for the created directory. * @param bool $recursive whether to create parent directories if they do not exist. * @return bool whether the directory is created successfully * @throws /yii/base/Exception if the directory could not be created (i.e. php error due to parallel changes) */ public static function createDirectory($path, $mode = 0775, $recursive = true) { if (is_dir($path)) { return true; } $parentDir = dirname($path); // recurse if parent dir does not exist and we are not at the root of the file system. if ($recursive && !is_dir($parentDir) && $parentDir !== $path) { static::createDirectory($parentDir, $mode, true); } try { if (!mkdir($path, $mode)) { return false; } } catch (/Exception $e) { if (!is_dir($path)) {// https://github.com/yiisoft/yii2/issues/9288 throw new /yii/base/Exception("Failed to create directory /"$path/": " . $e->getMessage(), $e->getCode(), $e); } } try { // return chmod($path, $mode); @chmod($path, $mode); return true; } catch (/Exception $e) { throw new /yii/base/Exception("Failed to change permissions for directory /"$path/": " . $e->getMessage(), $e->getCode(), $e); } } }
10、手动删除目录:/webtv/wangjie/pcs-api/tmp/2019/12,再次上传选题素材,上传资源成功,符合预期,如图8
11、查看挂载的目录,/webtv/wangjie/pcs-api/tmp/2019/12/05/1575537845.5862.1232301337.jpg 已经存在,符合预期,如图9
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/250499.html