web-dev-qa-db-ja.com

Laravel間違った権限で作成された毎日のログ

Php artisan(root user)を使用して実行するスクリプトがあり、Apache www-data userの前に毎日ログファイルが作成されることがあります-つまり、実際のユーザーがWebアプリケーションを使用すると、フォルダーのアクセス許可エラーが発生します。

ストリームを開けませんでした:許可が拒否されました

権限を毎回www-dataに戻しますが、常に正しい権限でログファイルを作成することでこれを解決したいと思います。

私は、ファイルを作成するか、ファイルに触れることで毎日適切な許可が得られるようにするcronジョブを作成することを検討しましたが、別のスクリプトに依存しないより良いソリューションを探しています。

また、PHPアーティザンを別のスクリプトでラップして、常にwww-dataクレデンシャルで実行されるようにすることも検討しましたが、実際にやりたいことはrootですApacheに許可されていない手順。

他に提案はありますか?

82
NiRR

定数から始めましょう。

rootによって実行されるphp artisanコマンドがあります。

このコマンドは毎日実行されると想定しても安全です。

解決策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:

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()はスクリプトの所有者名を返します。したがって、ソリューションno.1を適用するには、chown職人のクラスファイルを必要なユーザー名に追加します。

57
Mysteryos

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

もちろん、代わりに使用できる他のハンドラがたくさんあります。

61
Sam Wilson

Laravelバージョン5.6.10以降では、permissionおよびsingleドライバーの構成(config/logging.php)でdaily要素をサポートしています。

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

bootstrapスクリプトでMonologを操作する必要はありません。

具体的には、サポートが https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8 に追加されました。

55
crishoj

そのためには、ファイルとディレクトリで高度なACLを使用する必要があります。 setfaclはあなたの答えです。 www-dataに書き込み権限を与える場合root's特定のディレクトリにあるファイルは、次のように実行できます。

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

これを発行した後、/my/folder/のすべてのファイルのwww-dataユーザーのrwxにアクセス許可を設定していますそれら。参照用に this および this question を参照してください。また、 docs for setfacl を確認できます。

これが役立つかどうか教えてください。

20
Paweł Tomkiel

私にとって、この問題はログのアクセス許可よりもはるかに多くのものでした...ブートストラップ/キャッシュとストレージフォルダーに関連する問題があり、1人のユーザーはファイル/フォルダーを作成し、もう1人は標準のために編集/削除できません644および755権限。

典型的なシナリオは次のとおりです。

  • Apacheユーザーによって作成されているが、composer installコマンドの実行時に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(ユニットテストなど)を使用しているcomposerユーザーとキューデーモンを区別するのに役立ちました。

$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);
}); 
10
Andrew

私はこれが非常に簡単な方法で働いていました:

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
  • ログファイルは、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',
        ],
    ],
];
9
Lahar Shah

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);
});
7
Artur Käpp

ララヴェル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 で動作します

ララヴェル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 で動作します
4
rap-2-h

次のようなものを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グループに追加しました。

関連する微調整は、app/start/global.phpファイルの先頭に次を配置することです。

umask(0002);

これを行うと、上のchmod行が無効になります。 umaskをこれに設定すると、PHP(したがってLaravel)が作成するすべての新しいファイルは、「他の」ユーザーが書き込み権限を持たないように、権限のみがマスクされます。つまり、ディレクトリはrwxrwxr-xとして始まり、ファイルはrw-rw-r--として始まります。したがって、www-dataがPHPを実行している場合、そのユーザーのメイングループ(www-data)のすべてのユーザーは、デフォルトでキャッシュおよびログファイルに書き込み可能になります。

4
tremby

この作業を行う非Laravelの1つの方法は、cronジョブを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
3
user2662680

ララヴェル5.4

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

bootAppServiceProvider関数に追加

3
StupidDev

(Laravel 5.6)最近同じ問題に遭遇し、/app/Console/Kernel.phpで実行するようにスケジュールされたコマンドを設定しました。

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

私はそれがちょっとやり過ぎだと知っていますが、それは魅力のように機能し、それ以来問題はありませんでした。

2
Ague Mort

アーティザンコマンドでログファイルのアクセス許可を変更するだけです。

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

get_current_user() は、現在のスクリプトのユーザーを返します。

つまり、スクリプトをrootユーザーとして初期化しても、daily.logの所有者は常にwww-dataになります。

0
Adam

ララヴェル5.8

Laravel 5.8では、config/logging.phpでログ名を設定できます。

したがって、以前の回答とコメントを使用して、実際のposixユーザー名とphp_sapi_name()値の両方を使用してログに名前を付けたい場合は、ログ名セットのみを変更する必要があります。毎日のドライバーを使用すると、ユーザー/ APIの組み合わせごとに実行されるログローテーションが可能になり、ログを変更できるアカウントによってログが常にローテーションされるようになります。

また、ローカル環境に存在しないposix関数のチェックも追加しました。この場合、ログ名はデフォルトの標準になります。

デフォルトのログチャネル「daily」を使用していると仮定すると、「channels」キーを次のように変更できます。

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

これにより、アクセスポイントに応じてlaravel-cli-sfscs-2019-05-15.loglaravel-Apache2handler-Apache-2019-05-15.logなど、各組み合わせに固有のログ名が作成されます。

0
sfscs