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/webdev/181449.html
