Laravel 4 使用错误权限创建的Laravel每日日志
我有一个使用php artisan(使用root用户)运行的脚本,有时它会导致在apachewww data用户创建日志文件之前创建日志文件,这意味着当真实用户使用我的web应用程序时,我会收到文件夹权限错误: 无法打开流:权限被拒绝 每次我都会将权限更改回www data,但我希望通过始终使用正确的权限创建日志文件来解决此问题 我考虑过创建一个cron作业来创建文件或触摸它,以确保它每天都有正确的权限,但我正在寻找一个不依赖其他脚本的更好的解决方案 我们还考虑将php artisan封装在另一个脚本中,以确保它始终使用www data凭据运行,但我们要做的一些事情实际上是root过程,apache不应该允许这样做Laravel 4 使用错误权限创建的Laravel每日日志,laravel-4,file-permissions,Laravel 4,File Permissions,我有一个使用php artisan(使用root用户)运行的脚本,有时它会导致在apachewww data用户创建日志文件之前创建日志文件,这意味着当真实用户使用我的web应用程序时,我会收到文件夹权限错误: 无法打开流:权限被拒绝 每次我都会将权限更改回www data,但我希望通过始终使用正确的权限创建日志文件来解决此问题 我考虑过创建一个cron作业来创建文件或触摸它,以确保它每天都有正确的权限,但我正在寻找一个不依赖其他脚本的更好的解决方案 我们还考虑将php artisan封装在另一
还有什么建议吗?在
app/start/artisan.php
文件的开头添加如下内容(这是Laravel 4):
如果您提到的每日日志文件不是标准的Laravel日志文件,请调整路径。您也可能不想像我在这里所做的那样更改组或设置权限。上面将组设置为www-data
,并设置组写入权限。然后,我将常规用户添加到www-data
组中,这样,作为常规用户运行artisan命令仍然可以写入日志
一个相关的调整是将以下内容放在app/start/global.php
文件的开头:
umask(0002);
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that gets used when writing
| messages to the logs. The name specified in this option should match
| one of the channels defined in the "channels" configuration array.
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Out of
| the box, Laravel uses the Monolog PHP logging library. This gives
| you a variety of powerful log handlers / formatters to utilize.
|
| Available Drivers: "single", "daily", "slack", "syslog",
| "errorlog", "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily'],
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/' . php_sapi_name() . '/laravel.log'),
'level' => 'debug',
'days' => 7,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'level' => 'critical',
],
'syslog' => [
'driver' => 'syslog',
'level' => 'debug',
],
'errorlog' => [
'driver' => 'errorlog',
'level' => 'debug',
],
],
];
如果您这样做,上面的
chmod
行将变得没有意义。将umask设置为该值时,PHP(以及Laravel)生成的任何新文件都将被屏蔽权限,这样“其他”用户就不会有写权限。这意味着目录将以rwxrwxr-x
开头,文件以rw-rw-r--
开头。因此,如果www-data
正在运行PHP,它生成的任何缓存和日志文件默认情况下都可以由该用户的主组(即www-data
中的任何人写入。为此,您应该在文件和目录上使用高级ACLsetfacl
将是您的答案。如果您想授予www data用户权限,以便在特定目录下的root的文件上进行写入,您可以这样做:
setfacl -d -m default:www-data:you-chosen-group:rwx /my/folder
发出此命令后,您将为www data用户对/my/folder/
中所有文件的rwx
设置权限,无论这些文件是谁创建的。请参阅和以供参考。还有,你可以查一下
让我知道这是否有用。让我们从常量开始 您有一个
php artisan
命令,由root
运行
可以安全地假设该命令每天都执行
解决方案1:
假设创建文件的用户在默认情况下具有写入权限,我们可以按用户将日志分开:
App/start/global.php
/*
|--------------------------------------------------------------------------
| Application Error Logger
|--------------------------------------------------------------------------
|
| Here we will configure the error logger setup for the application which
| is built on top of the wonderful Monolog library. By default we will
| build a basic log file setup which creates a single file for logs.
|
*/
Log::useDailyFiles(storage_path().'/logs/laravel-'.get_current_user().'.log');
如果您的www数据用户创建错误日志,则会导致:storage/logs/laravel-www-data-2015-4-27.log
如果root用户要创建错误日志,则会导致:storage/logs/laravel-root-2015-4-27.log
解决方案2:
在php脚本中更改artisan命令使用的日志
在run()
函数中,在开头添加此行:
Log::useFiles(storage_path().'/logs/laravel-'.__CLASS__.'-'.Carbon::now()->format('Y-m-d').'.log');
如果类的名称为ArtisRunner
,则日志文件将为:
存储/logs/laravel-ArtisanRunner-2015-4-27.log
结论:解决方案1更好,因为它按用户描述日志,因此不会发生错误
编辑:正如jason指出的,
get\u current\u user()
返回脚本的所有者名称。因此,要应用解决方案1,chown
将artisan类文件设置为所需的用户名。对于Laravel 5.1,我在bootstrap/app.php
的底部使用以下内容(如中所述):
当然,还有很多其他的处理程序可以使用。Laravel 5.1 在本例中,我们希望创建所有日志文件,以便
deploy
组中的所有内容都具有读/写权限。因此,我们需要创建具有0664
权限的所有新文件,而不是0644
默认权限
我们还添加了一个格式化程序来添加换行符以提高可读性:
$app->configureMonologUsing(function(Monolog\Logger $monolog) {
$filename = storage_path('/logs/laravel.log');
$handler = new Monolog\Handler\RotatingFileHandler($filename, 0, \Monolog\Logger::DEBUG, true, 0664);
$handler->setFormatter(new \Monolog\Formatter\LineFormatter(null, null, true, true));
$monolog->pushHandler($handler);
});
也可以将此与公认的答案结合起来
$app->configureMonologUsing(function(Monolog\Logger $monolog) {
$filename = storage_path('/logs/laravel-' . php_sapi_name() . '.log');
$handler = new Monolog\Handler\RotatingFileHandler($filename, 0, \Monolog\Logger::DEBUG, true, 0664);
$handler->setFormatter(new \Monolog\Formatter\LineFormatter(null, null, true, true));
$monolog->pushHandler($handler);
});
对我来说,这个问题不仅仅是日志权限……我遇到了与引导/缓存和存储文件夹相关的任何问题,其中一个用户将创建一个文件/文件夹,而另一个用户由于标准644和755权限而无法编辑/删除 典型情况如下:
- 由apache用户创建的bootstrap/cache/compiled.php文件,但在执行composer安装命令时,composer用户不可编辑该文件
- apache用户正在创建无法使用composer用户清除的缓存
- 上述可怕的日志竞争条件
$app->configureMonologUsing(function(Monolog\Logger $monolog) {
$filename = storage_path('/logs/laravel-' . php_sapi_name() . '.log');
$handler = new Monolog\Handler\RotatingFileHandler($filename, 0, \Monolog\Logger::DEBUG, true, 0664);
$handler->setFormatter(new \Monolog\Formatter\LineFormatter(null, null, true, true));
$monolog->pushHandler($handler);
});
## create user group
sudo groupadd laravel
## add composer user to group
sudo gpasswd -a composer-user laravel
## add web server to group
sudo gpasswd -a apache laravel
## jump to laravel path
sudo cd /path/to/your/beautiful/laravel-application
## optional: temporary disable any daemons that may read/write files/folders
## For example Apache & Queues
## optional: if you've been playing around with permissions
## consider resetting all files and directories to the default
sudo find ./ -type d -exec chmod 755 {} \;
sudo find ./ -type f -exec chmod 644 {} \;
## give users part of the laravel group the standard RW and RWX
## permissions for the existing files and folders respectively
sudo chown -R :laravel ./storage
sudo chown -R :laravel ./bootstrap/cache
sudo find ./storage -type d -exec chmod 775 {} \;
sudo find ./bootstrap/cache -type d -exec chmod 775 {} \;
sudo find ./storage -type f -exec chmod 664 {} \;
sudo find ./bootstrap/cache -type f -exec chmod 664 {} \;
## give the newly created files/directories the group of the parent directory
## e.g. the laravel group
sudo find ./bootstrap/cache -type d -exec chmod g+s {} \;
sudo find ./storage -type d -exec chmod g+s {} \;
## let newly created files/directories inherit the default owner
## permissions up to maximum permission of rwx e.g. new files get 664,
## folders get 775
sudo setfacl -R -d -m g::rwx ./storage
sudo setfacl -R -d -m g::rwx ./bootstrap/cache
## Reboot so group file permissions refresh (required on Debian and Centos)
sudo shutdown now -r
## optional: enable any daemons we disabled like Apache & Queues
$app->configureMonologUsing(function(MonologLogger $monolog) {
$processUser = posix_getpwuid(posix_geteuid());
$processName= $processUser['name'];
$filename = storage_path('logs/laravel-'.php_sapi_name().'-'.$processName.'.log');
$handler = new MonologHandlerRotatingFileHandler($filename);
$monolog->pushHandler($handler);
});
$app->configureMonologUsing(function (Monolog\Logger $monolog) {
$filename = storage_path('logs/' . php_sapi_name() . '-' . posix_getpwuid(posix_geteuid())['name'] . '.log');
$monolog->pushHandler($handler = new Monolog\Handler\RotatingFileHandler($filename, 30));
$handler->setFilenameFormat('laravel-{date}-{filename}', 'Y-m-d');
$formatter = new \Monolog\Formatter\LineFormatter(null, null, true, true);
$formatter->includeStacktraces();
$handler->setFormatter($formatter);
});
<?php
namespace App;
use Monolog\Logger as MonologLogger;
class Logger {
public function __invoke(array $config)
{
$monolog = new MonologLogger('my-logger');
$filename = storage_path('logs/' . php_sapi_name() . '-' . posix_getpwuid(posix_geteuid())['name'] . '.log');
$monolog->pushHandler($handler = new \Monolog\Handler\RotatingFileHandler($filename, 30));
$handler->setFilenameFormat('laravel-{date}-{filename}', 'Y-m-d');
$formatter = new \Monolog\Formatter\LineFormatter(null, null, true, true);
$formatter->includeStacktraces();
$handler->setFormatter($formatter);
return $monolog;
}
}
'channels' => [
'custom' => [
'driver' => 'custom',
'via' => App\Logging\CreateCustomLogger::class,
],
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/' . php_sapi_name() . '/laravel.log'),
'level' => 'debug',
'days' => 7,
]
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that gets used when writing
| messages to the logs. The name specified in this option should match
| one of the channels defined in the "channels" configuration array.
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Out of
| the box, Laravel uses the Monolog PHP logging library. This gives
| you a variety of powerful log handlers / formatters to utilize.
|
| Available Drivers: "single", "daily", "slack", "syslog",
| "errorlog", "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily'],
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/' . php_sapi_name() . '/laravel.log'),
'level' => 'debug',
'days' => 7,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'level' => 'critical',
],
'syslog' => [
'driver' => 'syslog',
'level' => 'debug',
],
'errorlog' => [
'driver' => 'errorlog',
'level' => 'debug',
],
],
];
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 7,
'permission' => 0664,
],
# config/logging.php
'channels' => [
...
'daily' => [
'driver' => 'daily',
'path' => storage_path(
function_exists('posix_getpwuid')
&& function_exists('posix_geteuid')
? 'logs/laravel'
. '-' . php_sapi_name()
. '-' . posix_getpwuid(posix_geteuid())['name']
. '.log'
: 'logs/laravel.log'),
'level' => 'debug',
'days' => 15,
],
...
$path = storage_path('log/daily.log');
chown($path, get_current_user());
find /path/to/your/root/dir/ -type f -exec chmod 644 {} \;
find /path/to/your/root/dir/ -type d -exec chmod 755 {} \;
chown -R www-data:www-data /path/to/your/root/dir/
chgrp -R www-data storage bootstrap/cache
chmod -R ug+rwx storage bootstrap/cache
php artisan key:generate
php artisan cache:clear
php artisan config:clear
composer dump-autoload
php artisan migrate //only if not already migrated
#!/bin/bash
DIRS="storage current/bootstrap/cache"
MASTER_PATH={{MASTER_PATH}}
if [ -d $MASTER_PATH ]; then
cd $MASTER_PATH
for p in `ls $MASTER_PATH`; do
if [ -d $MASTER_PATH/$p ]; then
cd $MASTER_PATH/$p
echo "Project: $p -> $MASTER_PATH/$p"
for i in $DIRS; do
echo "- directory: $i"
if [ -d $i ]; then
echo "-- checking ACL..."
HAS_ACL=`getfacl -p $i | grep "^user:{{WEB_SERVER_USER}}:.*w" | wc -l`
if [ $HAS_ACL -eq 0 ]; then
echo "--- applying $i"
setfacl -L -R -m u:{{WEB_SERVER_USER}}:rwX -m u:{{DEPLOYMENT_USER}}:rwX $i
setfacl -dL -R -m u:{{WEB_SERVER_USER}}:rwX -m u:{{DEPLOYMENT_USER}}:rwX $i
else
echo "--- skipping $i"
fi
fi
done
echo "--------------"
fi
done
else
echo "No $MASTER_PATH - skipping overall"
fi
PROJECT_DIRS="storage"
RELEASE_DIRS="bootstrap/cache"
cd {{ project }}
for i in $PROJECT_DIRS; do
if [ -d $i ]; then
HAS_ACL=`getfacl -p $i | grep "^user:{{WEB_SERVER_USER}}:.*w" | wc -l`
if [ $HAS_ACL -eq 0 ]; then
echo "ACL set for directory {{project}}/$i"
setfacl -L -R -m u:{{WEB_SERVER_USER}}:rwX -m u:{{DEPLOYMENT_USER}}:rwX $i
setfacl -dL -R -m u:{{WEB_SERVER_USER}}:rwX -m u:{{DEPLOYMENT_USER}}:rwX $i
fi
fi
done
cd {{ release }}
for i in $RELEASE_DIRS; do
if [ -d $i ]; then
HAS_ACL=`getfacl -p $i | grep "^user:{{WEB_SERVER_USER}}:.*w" | wc -l`
if [ $HAS_ACL -eq 0 ]; then
echo "ACL set for directory {{project}}/$i"
setfacl -L -R -m u:{{WEB_SERVER_USER}}:rwX -m u:{{DEPLOYMENT_USER}}:rwX $i
setfacl -dL -R -m u:{{WEB_SERVER_USER}}:rwX -m u:{{DEPLOYMENT_USER}}:rwX $i
fi
fi
done
cd /path/to/project
chown -R www-data:root .
chmod -R g+s .