使用错误权限创建的Laravel每日日志

NiR*_*iRR 89 file-permissions laravel-4

我有一个脚本,我使用php artisan(使用root用户)运行,有时它会导致在apache www-data用户之前创建每日日志文件- 这意味着当真实用户使用我的Web应用程序时,我得到文件夹权限错误:

无法打开流:权限被拒绝

我每次都将权限更改回www-data,但我想通过始终使用正确的权限创建日志文件来解决此问题.

我考虑创建一个创建文件或触摸它的cron作业,以确保它每天都有正确的权限,但我正在寻找一个不依赖于另一个脚本的更好的解决方案.

我们还考虑将php artisan包装在另一个脚本中,以确保它始终使用www-data凭据运行,但我们想要做的事情实际上是不允许apache 执行的root程序.

还有什么建议吗?

cri*_*hoj 68

Laravel 5.6.10及更高版本支持permission配置(config/logging.php)中的元素singledaily驱动程序:

    'daily' => [
        'driver' => 'daily',
        'path' => storage_path('logs/laravel.log'),
        'level' => 'debug',
        'days' => 7,
        'permission' => 0664,
    ],
Run Code Online (Sandbox Code Playgroud)

无需在引导脚本中使用Monolog.

具体而言,在https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8中添加了支持.

  • `'permission' => 0664` 对我有用(不带引号) (13认同)
  • 这应该在官方文件中! (6认同)
  • 这并不能解决问题,因为它不会更改文件的所有者或组。两者仍然是“root”,当“www-data”运行的脚本想要写入此文件时,仍然不允许这样做。@mysteryos 的答案解决了问题(至少对我来说)。 (4认同)
  • 简单且有效(尝试5.7版),很好找到! (2认同)
  • 此答案中缺少撇号。它应该是“ permission” =>“ 0664”。那么这个答案就很好! (2认同)
  • @Phil Nope-这只是Monologs流处理程序的包装,该处理程序接受int的权限。Monolog包装http://php.net/manual/zh/function.chmod.php-注意,必须确保前导0以确保它是八进制值 (2认同)
  • @Friedrich如果您的日志文件是使用“root”作为文件所有者创建的,则可能表明您在网络服务器的设置方式方面存在更大的问题 (2认同)

Sam*_*son 61

对于Laravel 5.1,我在底部使用以下内容bootstrap/app.php(如文档所述):

/**
 * Configure Monolog.
 */
$app->configureMonologUsing(function(Monolog\Logger $monolog) {
    $filename = storage_path('logs/laravel-'.php_sapi_name().'.log');
    $handler = new Monolog\Handler\RotatingFileHandler($filename);
    $monolog->pushHandler($handler);
});
Run Code Online (Sandbox Code Playgroud)

当然,你可以使用许多其他处理程序.


Mys*_*yos 59

让我们从常量开始.

你有一个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');
Run Code Online (Sandbox Code Playgroud)

如果您的www-data用户要创建错误日志,则会导致: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');
Run Code Online (Sandbox Code Playgroud)

如果您的班级名称是ArtisanRunner,那么您的日志文件将是:

storage/logs/laravel-ArtisanRunner-2015-4-27.log.

结论:解决方案编号1更好,因为它描述了用户的日志,因此不会发生错误.

编辑:正如杰森指出的那样,get_current_user()返回脚本的所有者名称.因此,对于要应用的解决方案1,chown您的工匠类文件将为所需的用户名.

  • 请注意,`get_current_user()`返回当前PHP脚本的所有者(根据php.net),而不是当前正在运行*脚本的用户.我使用`php_sapi_name()`代替,它给出了php处理程序的名称(例如apache或cli),它们往往以不同的用户身份运行. (11认同)
  • 这需要为最新的 Laravel 版本更新:v5+ (3认同)

Paw*_*iel 21

出于此目的,您应该在文件和目录上使用高级ACL.setfacl这是你的答案.如果你想给www-data用户授权在特定目录下的root文件上写,你可以这样做:

setfacl -d -m default:www-data:you-chosen-group:rwx /my/folder
Run Code Online (Sandbox Code Playgroud)

发出此命令后,无论是谁创建了这些文件,您都要rwx为所有文件的www-data用户设置权限/my/folder/.请看这个这个问题以供参考.此外,您可以检查文档setfacl.

如果这有帮助,请告诉我.

  • 以下命令对我有用:`setfacl -d -mg:www-data:rw/full/path/to/laravel/storage/logs`后跟`php artisan cache:clear`和`composer dump-autoload`. (2认同)

And*_*rew 11

对我来说,这个问题不仅仅是日志权限......我遇到了与引导程序/缓存和存储文件夹相关的任何问题,其中一个用户将创建文件/文件夹,另一个用户将无法编辑/删除644和755权限.

典型情况是:

  • bootstrap/cache/compiled.php文件由apache用户创建,但在执行composer install命令时由编写者用户无法编辑

  • apache用户创建无法使用composer用户清除的缓存

  • 可怕的原木竞争条件如上所述.

梦想是无论哪个用户创建文件/文件夹,其他需要访问的用户都具有与原始作者完全相同的权限.

TL; DR?

这是它的完成方式.

我们需要创建一个名为laravel的共享用户组,该组由需要访问存储和引导/缓存目录的所有用户组成.接下来,我们需要确保新创建的文件和文件夹分别具有laravel组和664和775权限.

现在的文件/目录很容易做到这一点,但需要一点魔力来调整默认文件/文件夹创建规则......

## 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
Run Code Online (Sandbox Code Playgroud)

纯粹出于调试目的,我发现将日志分成两个cli/web +用户是有益的,所以我稍微修改了Sam Wilson的答案.我的用例是队列在它自己的用户下运行,因此它帮助区分使用cli的作曲家用户(例如单元测试)和队列守护进程.

$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);
}); 
Run Code Online (Sandbox Code Playgroud)


Lah*_*hah 9

我有这个非常简单的方法:

我在Laravel 5.6上遇到了同样的问题

config/logging.php我刚刚更新了每日频道的路径值php_sapi_name().

这会为不同的php_sapi_name创建单独的durectory,并将带有时间戳的日志文件放入其特定目录中.

'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/' . php_sapi_name() . '/laravel.log'),
            'level' => 'debug',
            'days' => 7,
        ]
Run Code Online (Sandbox Code Playgroud)

所以对我来说,

  • 日志文件在fpm-fcgi目录下创建:来自网站的日志,owner: www-data
  • 日志文件在cli目录下创建:来自artisan命令(cronjob).owner: root

有关Laravel 5.6日志的更多信息:https://laravel.com/docs/5.6/logging

这是我的config/logging.php档案:

<?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',
        ],
    ],
];
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用 `artisan config:cache` 缓存配置,这将不起作用,因为它将使用 cli SAPI 创建配置缓存,该缓存将用于 CLI 和 Web 请求。 (3认同)

use*_*680 9

完成这项工作的一种非 Laravel 方法是简单地将您的 cronjob 执行为 www-data。

例如https://askubuntu.com/questions/189189/how-to-run-crontab-as-userwww-data

/etc/crontab

*/5 * * * * www-data php /var/www/public/voto_m/artisan top >/dev/null 2>&1
Run Code Online (Sandbox Code Playgroud)


Art*_*äpp 7

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);
});
Run Code Online (Sandbox Code Playgroud)

此外,还可以将其与已接受的答案相结合

$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);
});
Run Code Online (Sandbox Code Playgroud)


rap*_*2-h 5

Laravel 5.5

将此代码添加到bootstrap/app.php

$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);
});
Run Code Online (Sandbox Code Playgroud)
  • 它将存储这样的文件:laravel-2018-01-27-cli-raph.log并且laravel-2018-01-27-fpm-cgi-raph.log更具可读性。
  • 保留新行(从默认 Laravel 行为开始)
  • 它适用于Laravel 日志查看器

Laravel 5.6

必须为记录器创建一个类

<?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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您必须在以下位置注册它config/logging.php

'channels' => [
    'custom' => [
        'driver' => 'custom',
        'via' => App\Logging\CreateCustomLogger::class,
    ],
],
Run Code Online (Sandbox Code Playgroud)

与 5.5 相同的行为:

  • 它将存储这样的文件:laravel-2018-01-27-cli-raph.log并且laravel-2018-01-27-fpm-cgi-raph.log更具可读性。
  • 保留新行(从默认 Laravel 行为开始)
  • 它适用于Laravel 日志查看器