Laravel daily log создан с неверными разрешениями



У меня есть скрипт, который я запускаю с помощью php artisan (с root user), и иногда это приводит к созданию файла Ежедневного журнала перед apache www-data пользователь делает - это означает, что когда реальный пользователь использует мое веб-приложение, я получаю ошибку разрешения папки:

не удалось открыть поток: разрешение отказано

Я меняю разрешения обратно на www-data каждый раз, но я хочу решить эту проблему в файл журнала всегда создается с правильными разрешениями.

Я рассматривал возможность создания задания cron, которое создает файл или касается его, чтобы убедиться, что у него есть правильное разрешение каждый день, но я ищу лучшее решение, которое не зависит от другого сценария.

мы также рассмотрели обертывание php artisan в другой скрипт, чтобы убедиться, что он всегда работает с www-data учетные данные, но то, что мы хотим делать на самом деле root процедуры, которые apache не должно быть разрешено делать.

есть еще предложения?

413   13  

13 ответов:

давайте начнем с того, что является постоянным.

у вас , управляемый 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-data пользователь должен был создать журнал ошибок, это приведет к: storage/logs/laravel-www-data-2015-4-27.log.

если root пользователь должен был создать журнал ошибок, это приведет к: storage/logs/laravel-root-2015-4-27.log.

Решение № 2:

измените журнал, используемый вашей командой artisan, в вашем PHP-скрипте.

в своем run() функция, добавьте эту строку в начале:

Log::useFiles(storage_path().'/logs/laravel-'.__CLASS__.'-'.Carbon::now()->format('Y-m-d').'.log');

если имя вашего класса ArtisanRunner, то файл журнала быть:

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

вывод: Решение № 1 лучше, учитывая, что оно определяет ваши журналы пользователем, и, следовательно, никаких ошибок не произойдет.

EDIT: как указал Джейсон,get_current_user() возвращает имя владельца скрипта. Следовательно, для решения № 1, чтобы применить,chown ваши файлы класса artisan с требуемым именем пользователя.

для 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);
});

есть много других обработчиков, которые вы можете использовать, конечно.

для таких целей вы должны использовать расширенный ACL для ваших файлов и каталогов. setfacl был бы ваш ответ здесь. Если вы хотите дать www-data права пользователя на запись корень файлы в определенном каталоге, вы можете сделать это так:

setfacl -d -m default:www-data:you-chosen-group:rwx /my/folder

после выдачи этого вы устанавливаете разрешения rwx на www-data пользователь на всех файлах в /my/folder/ независимо от того, кто создал их. Пожалуйста, смотрите этой и этот вопрос для справки. Кроме того, вы можете проверить документы на setfacl.

Дайте мне знать, если это помогает.

для меня эта проблема была гораздо больше, чем разрешения журнала...У меня были проблемы со всем, что связано с папками bootstrap/cache и storage, где один пользователь создавал файл/папку, а другой не мог редактировать/удалять из-за стандартных разрешений 644 и 755.

типичные сценарии:

  • bootstrap / cache / compiled.php-файл создается пользователем apache, но не редактируется пользователем composer при выполнении установки composer команда

  • пользователь apache создает кэш, который не может быть очищен с помощью пользователя composer

  • Страшные условия гонки журнала, описанные выше.

мечта заключается в том, что независимо от того, какой пользователь создает файл/папку, другие пользователи, которым нужен доступ имеют точно такие же права, что и автор оригинала.

TL; DR?

вот как это делается.

нам нужно создать общая группа пользователей называется laravel, группа состоит из всех пользователей, которым необходим доступ к каталогам хранения и начальной загрузки/кэша. Далее нам нужно убедиться, что вновь созданные файлы и папки имеют разрешения laravel group и 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: 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

чисто для целей отладки я обнаружил разделение журналов на оба пользователя cli / web + были полезны, поэтому я немного изменил ответ Сэма Уилсона. Мой вариант использования-очередь, запущенная под собственным пользователем, поэтому он помог отличить пользователя composer, использующего 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);
}); 

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);
});

Laravel версии 5.6.10 и позже имеет поддержку permission элемент в конфигурации single и daily водитель:

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

нет необходимости жонглировать монологом в сценарии начальной загрузки.

в частности, была добавлена поддержка https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8.

я столкнулся с той же проблемой на Laravel 5.6

на config/logging.php Я только что обновил значение пути ежедневного канала с php_sapi_name() в нем.

это создает отдельный durectory для разных php_sapi_name и помещает файл журнала с отметкой времени в их пертикулярный каталог.

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

для меня

  • файлы журнала создаются под fpm-fcgi каталог: журналы с сайта, owner: www-data
  • файлы журнала создано под cli каталог: из команды artisan(cronjob). owner: root

дополнительная информация о Laravel 5.6 logging:https://laravel.com/docs/5.6/logging

вот мой config/logging.php file:

<?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',
        ],
    ],
];

добавить что-то вроде следующего, чтобы начать свой app/start/artisan.php файл (это с Laravel 4):

// If effectively root, touch the log file and make sure it belongs to www-data
if (posix_geteuid() === 0) {
    $file = storage_path() . '/logs/laravel.log';
    touch($file);
    chown($file, 'www-data');
    chgrp($file, 'www-data');
    chmod($file, 0664);
}

отрегулируйте путь, если файл Ежедневного журнала, который вы упомянули, не является стандартным файлом журнала Laravel. Вы также не можете изменить группу или установить разрешения, как я делаю здесь. Выше устанавливает группу в www-data и устанавливает групповые разрешения на запись. Затем я добавил своего обычного пользователя в www-data группа так, что запуск команды artisan как мой обычный пользователь может все еще запишите в журнал.

связанная настройка заключается в том, чтобы поместить следующее В начале вашего app/start/global.php file:

umask(0002);

если вы сделаете это chmod строка выше становится спорной. С помощью umask, установленного на это, любые новые файлы PHP (и, следовательно, Laravel) будут иметь свои разрешения, замаскированные только для того, чтобы "другие" пользователи не имели разрешений на запись. Это означает, что каталоги будут начинаться как rwxrwxr-x и файлы как rw-rw-r--. Так что если www-data работает PHP, любые файлы кэша и журнала, которые он делает будет записываться по умолчанию кем-либо в основной группе этого пользователя, которая является www-data.

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);
});
  • он будет хранить файлы, как это:laravel-2018-01-27-cli-raph.log и laravel-2018-01-27-fpm-cgi-raph.log что более читабельно.
  • новые строки сохраняются (по умолчанию поведение Laravel)
  • он работает с Laravel Log Viewer

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;
    }
}

тогда, вы должны зарегистрируйте его в config/logging.php:

'channels' => [
    'custom' => [
        'driver' => 'custom',
        'via' => App\Logging\CreateCustomLogger::class,
    ],
],

то же поведение, что и для 5.5:

  • он будет хранить файлы, как это:laravel-2018-01-27-cli-raph.log и laravel-2018-01-27-fpm-cgi-raph.log что более читабельно.
  • новые строки сохраняются (по умолчанию поведение Laravel)
  • он работает с Laravel Log Viewer

Laravel 5.4

\Log::getMonolog()->popHandler(); \Log::useDailyFiles(storage_path('/logs/laravel-').get_current_user().'.log');

добавить

один не-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

(Laravel 5.6) недавно я столкнулся с той же проблемой, и я просто установил запланированную команду для запуска в /app/Console/Kernel.php.

$schedule->exec('chown -R www-data:www-data /var/www/**********/storage/logs')->everyMinute();

Я знаю, что это немного перебор, но он работает как шарм и с тех пор не было никаких проблем.

лучший способ, который я нашел, это то, что фиделопер предлагает,http://fideloper.com/laravel-log-file-name, Вы можете установить конфигурацию журнала laravel без класса журнала касания. Есть разные имена для консольных программ и Http-программ, я думаю, это лучшее решение.

    Ничего не найдено.

Добавить ответ:
Отменить.