Php artisan(root user)を使用して実行するスクリプトがあり、Apache www-data userの前に毎日ログファイルが作成されることがあります-つまり、実際のユーザーがWebアプリケーションを使用すると、フォルダーのアクセス許可エラーが発生します。
ストリームを開けませんでした:許可が拒否されました
権限を毎回www-dataに戻しますが、常に正しい権限でログファイルを作成することでこれを解決したいと思います。
私は、ファイルを作成するか、ファイルに触れることで毎日適切な許可が得られるようにするcronジョブを作成することを検討しましたが、別のスクリプトに依存しないより良いソリューションを探しています。
また、PHPアーティザンを別のスクリプトでラップして、常にwww-dataクレデンシャルで実行されるようにすることも検討しましたが、実際にやりたいことはrootですApacheに許可されていない手順。
他に提案はありますか?
定数から始めましょう。
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
職人のクラスファイルを必要なユーザー名に追加します。
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
および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 に追加されました。
そのためには、ファイルとディレクトリで高度な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
を確認できます。
これが役立つかどうか教えてください。
私にとって、この問題はログのアクセス許可よりもはるかに多くのものでした...ブートストラップ/キャッシュとストレージフォルダーに関連する問題があり、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);
});
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',
],
],
];
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);
});
このコードを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
(読みやすい)。クラスを作成する必要があります ロガーの場合:
<?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
(読みやすい)。次のようなものを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
)のすべてのユーザーは、デフォルトでキャッシュおよびログファイルに書き込み可能になります。
この作業を行う非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
ララヴェル5.4
\Log::getMonolog()->popHandler(); \Log::useDailyFiles(storage_path('/logs/laravel-').get_current_user().'.log');
boot
のAppServiceProvider
関数に追加
(Laravel 5.6)最近同じ問題に遭遇し、/app/Console/Kernel.php
で実行するようにスケジュールされたコマンドを設定しました。
$schedule->exec('chown -R www-data:www-data /var/www/**********/storage/logs')->everyMinute();
私はそれがちょっとやり過ぎだと知っていますが、それは魅力のように機能し、それ以来問題はありませんでした。
アーティザンコマンドでログファイルのアクセス許可を変更するだけです。
$path = storage_path('log/daily.log');
chown($path, get_current_user());
get_current_user() は、現在のスクリプトのユーザーを返します。
つまり、スクリプトをroot
ユーザーとして初期化しても、daily.log
の所有者は常にwww-data
になります。
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.log
やlaravel-Apache2handler-Apache-2019-05-15.log
など、各組み合わせに固有のログ名が作成されます。