IT story

잘못된 권한으로 생성 된 Laravel 일일 로그

hot-time 2020. 9. 17. 18:55
반응형

잘못된 권한으로 생성 된 Laravel 일일 로그


php artisan ( 루트 사용자 포함)을 사용하여 실행하는 스크립트가 있으며 때로는 apache www-data 사용자가 수행 하기 전에 일일 로그 파일이 생성 됩니다. 즉, 실제 사용자가 내 웹 응용 프로그램을 사용할 때 폴더 권한 오류 :

스트림을 열지 못했습니다. 권한이 거부되었습니다.

매번 권한을 www-data로 다시 변경 하지만 항상 올바른 권한으로 로그 파일을 생성하여이 문제를 해결하고 싶습니다.

파일을 생성하거나 매일 올바른 권한이 있는지 확인하기 위해 파일을 만지는 cron 작업을 만드는 것을 고려했지만 다른 스크립트에 의존하지 않는 더 나은 솔루션을 찾고 있습니다.

우리는 또한 php artisan을 다른 스크립트에 래핑하여 항상 www-data 자격 증명으로 실행되도록 하는 것을 고려했지만 우리가 원하는 것은 실제로 아파치가 허용해서는 안되는 루트 프로 시저입니다.

더 많은 제안이 있습니까?


일정한 것부터 시작합시다.

php artisan의해 실행되는 명령이 있습니다 root.

이 명령이 매일 실행된다고 가정하는 것이 안전합니다.

솔루션 No 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.

귀하의 경우 루트 사용자가 오류 로그를 생성했다, 그것의 결과 다음과 같습니다 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');

클래스 이름이 ArtisanRunner인 경우 로그 파일은 다음과 같습니다.

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

결론 : 솔루션 번호 1은 사용자별로 로그를 설명하므로 오류가 발생하지 않기 때문에 더 좋습니다.

편집 : jason이 지적한대로 get_current_user()스크립트의 소유자 이름을 반환합니다. 따라서 1 번 솔루션을 적용 chown하려면 필요한 사용자 이름에 장인 클래스 파일을 입력해야합니다.


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

물론 대신 사용할 수있는 다른 핸들러가 많이 있습니다.


Laravel 버전 5.6.10 이상 드라이버에 대한 permission구성 ( config/logging.php) 요소를 지원합니다 .singledaily

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

부트 스트랩 스크립트에서 Monolog로 저글링 할 필요가 없습니다.

특히 https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8에 지원이 추가되었습니다 .


이러한 목적을 위해 파일 및 디렉토리에 고급 ACL을 사용해야합니다. setfacl여기에 당신의 대답이 될 것입니다. www-data 사용자 에게 특정 디렉토리 의 루트 파일에 쓸 수있는 권한을 부여하려면 다음과 같이 할 수 있습니다.

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

이것을 발행 한 후에는 누가 생성했는지에 관계없이 모든 파일에 rwx대해 www-data 사용자에 대한 권한을 설정 /my/folder/합니다. 을 참조하시기 바랍니다 이 질문에 참조 할 수 있습니다. 또한 문서에서setfacl .

이것이 도움이되는지 알려주세요.


나에게이 문제는 로그 권한 이상이었습니다 ... 한 사용자가 파일 / 폴더를 만들고 다른 사용자가 표준으로 인해 편집 / 삭제할 수없는 부트 스트랩 / 캐시 및 스토리지 폴더와 관련된 문제가있었습니다. 644 및 755 권한.

일반적인 시나리오는 다음과 같습니다.

  • apache 사용자가 생성하지만 composer 설치 명령을 수행 할 때 composer 사용자가 편집 할 수없는 bootstrap / cache / compiled.php 파일

  • composer 사용자를 사용하여 지울 수없는 캐시를 생성하는 Apache 사용자

  • 위에서 설명한 두려운 로그 경쟁 조건.

꿈은 어떤 사용자가 파일 / 폴더를 생성하든 관계없이 액세스해야하는 다른 사용자가 원래 작성자와 동일한 권한을 갖는 것입니다.

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

순전히 디버깅 목적으로 로그 아웃을 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);
}); 

나는 이것이 매우 간단한 방법으로 작동했습니다.

Laravel 5.6 에서 같은 문제가 발생했습니다.

에서 config/logging.php방금 일일 채널의 경로 값을 업데이트 php_sapi_name()했습니다.

이렇게하면 다른 php_sapi_name에 대해 별도의 내구성이 생성되고 타임 스탬프가있는 로그 파일이 해당 디렉토리에 저장됩니다.

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

그래서 저는

  • 로그 파일은 다음 fpm-fcgi디렉토리 에 생성됩니다 . 웹 사이트의 로그,owner: www-data
  • 로그 파일은 cliartisan 명령 (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',
        ],
    ],
];

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

app/start/artisan.php파일 시작 부분에 다음과 같은 내용을 추가 합니다 (라 라벨 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);
}

Adjust the path if the daily log file you mention is not the standard Laravel log file. You also may not want to change the group or set the permissions as I am doing here. The above sets the group to www-data and sets group write permissions. I've then added my regular user to the www-data group so that running artisan commands as my regular user can still write to the log.

A related tweak is to put the following at the start of your app/start/global.php file:

umask(0002);

If you do this the chmod line above becomes moot. With the umask set to this, any new files PHP (and therefore Laravel) makes will have their permissions masked only so that "other" users won't have write permissions. This means directories will start as rwxrwxr-x and files as rw-rw-r--. So if www-data is running PHP, any cache and log files it makes will be writeable by default by anyone in that user's main group, which is www-data.


Laravel 5.5

Add this code to 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);
});
  • It will store files like this: laravel-2018-01-27-cli-raph.log and laravel-2018-01-27-fpm-cgi-raph.log which is more readable.
  • New lines are preserved (as of default Laravel behavior)
  • It works with Laravel Log Viewer

Laravel 5.6

You have to create a class for your logger:

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

Then, you have to register it in config/logging.php:

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

Same behavior as for 5.5:

  • It will store files like this: laravel-2018-01-27-cli-raph.log and laravel-2018-01-27-fpm-cgi-raph.log which is more readable.
  • New lines are preserved (as of default Laravel behavior)
  • It works with Laravel Log Viewer

Laravel 5.4

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

add to boot function in AppServiceProvider


One non-Laravel way to make this work is to simply executure your cronjob as www-data.

eg 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) I recently ran into the same problem and I simply set a scheduled command to run in /app/Console/Kernel.php.

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

I know it's a little bit of overkill, but it works like a charm and haven't had any issues since.


Laravel 5.8

Laravel 5.8 lets you set the log name in config/logging.php.

So using previous answers and comments, if you want to name you log using both the actual posix user name AND the php_sapi_name() value, you only need to change the log name set. Using the daily driver allows log rotation that runs per user / api combination which will ensure that the log is always rotated by an account that can modify the logs.

I also added a check for the posix functions which may not exist on your local environment, in which case the log name just defaults to the standard.

Assuming you are using the default log channel 'daily', you can modify your 'channels' key like so:

# 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,
    ],
    ...

This will result in a log name that should be unique to each combination such as laravel-cli-sfscs-2019-05-15.log or laravel-apache2handler-apache-2019-05-15.log depending on your access point.


You could simply change the permission of the log file in your artisan command:

$path = storage_path('log/daily.log');
chown($path, get_current_user());

where get_current_user() will return the user of the current script.

In other words, daily.log will always have www-data as its owner, even if you initialize the script as root user.


The best way I found is that fideloper suggest, http://fideloper.com/laravel-log-file-name, you can set laravel log configuration without touch Log class. Have differents names for Console programs and Http programs, I think, is the best solution.

참고URL : https://stackoverflow.com/questions/27674597/laravel-daily-log-created-with-wrong-permissions

반응형