Journal de bord quotidien de Laravel créé avec de mauvaises permissions

j'ai un script que j'exécute en utilisant php artisan( avec root utilisateur), et parfois il provoque le fichier journal quotidien à être créé avant l'apache www-data utilisateur fait - ce qui signifie que quand un utilisateur réel utilise mon application web, Je reçois le dossier erreur de permission:

N'a pas ouvert le flux: Permission refusée

je modifier les autorisations www-data à chaque fois mais je veux résoudre cela en ayant le fichier log toujours créé avec les permissions correctes.

j'ai envisagé de créer un travail cron qui crée le fichier ou le touche pour s'assurer qu'il a la bonne permission tous les jours, mais je suis à la recherche d'une meilleure solution qui ne repose pas sur un autre script.

nous avons également considéré envelopper php artisan dans un autre script pour s'assurer qu'il est toujours exécuté avec le www-data , mais quelque chose que nous voulons faire sont en fait des procédures root qu'apache ne devrait pas être autorisé à faire.

d'autres suggestions?

57
demandé sur Moshe Katz 2014-12-28 10:52:08

13 réponses

commençons par ce qui est constant.

vous avez une commande php artisan , exécutée par root .

on peut supposer que cette commande est exécutée quotidiennement.

Solution N ° 1:

étant Donné que l'utilisateur qui crée les fichiers est celui qui a la permission d'écrire par défaut, nous pouvons séparer les logs par l'utilisateur en tant que tel:

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

si votre www-data utilisateur devait créer un journal des erreurs, il en résulterait: storage/logs/laravel-www-data-2015-4-27.log .

si votre root utilisateur devait créer un journal des erreurs, il en résulterait: storage/logs/laravel-root-2015-4-27.log .

Solution N ° 2:

changez le log utilisé par votre commande artisan, dans votre script php.

dans votre fonction run() , Ajoutez cette ligne au début:

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

si le nom de votre classe est ArtisanRunner , alors votre fichier journal sera:

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

Conclusion: la Solution numéro 1 est meilleure, étant donné qu'elle délimite vos journaux par utilisateur, et donc aucune erreur ne se produira.

EDIT: comme l'a souligné jason, get_current_user() renvoie le script nom de propriétaire. Par conséquent, pour la solution no.1 pour appliquer, chown vos fichiers de classe artisan au nom d'utilisateur requis.

50
répondu Mysteryos 2016-01-07 16:34:35

pour Laravel 5.1 j'utilise ce qui suit vers le bas de bootstrap/app.php (comme indiqué dans the docs ):

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

il y a beaucoup d'autres Handlers que vous pouvez utiliser à la place, bien sûr.

57
répondu Sam Wilson 2016-01-22 04:39:33

à ces fins, vous devez utiliser advanced ACL sur vos fichiers et répertoires. setfacl serait votre réponse ici. Si vous voulez donner www-data permissions de l'utilisateur pour écrire sur root fichiers dans le répertoire spécifique, vous pouvez le faire comme ceci:

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

après avoir émis ceci vous définissez les permissions à rwx pour www-data utilisateur sur tous les fichiers dans /my/folder/ peu importe qui créé ceux-ci. Voir cette et cette question pour référence. Aussi, vous pouvez cocher docs pour setfacl .

dites-moi si ça peut aider.

19
répondu Paul Tomkiel 2017-04-13 12:36:31

pour moi ce problème était bien plus que des permissions log...J'ai eu des problèmes avec tout ce qui concerne le bootstrap/cache et les dossiers de stockage où un utilisateur créerait un fichier/dossier et l'autre serait incapable de modifier/supprimer en raison des permissions standard 644 et 755.

les scénarios typiques sont:

  • Le bootstrap/cache/compilé.fichier php créé par l'utilisateur apache mais non éditable par l'utilisateur composer lors de l'exécution de la commande composer install

  • l'utilisateur apache créant un cache qui ne peut pas être effacé en utilisant l'utilisateur composer

  • Le redoutable journal de la race des conditions décrites ci-dessus.

le rêve est que peu importe quel utilisateur crée le fichier/dossier, les autres utilisateurs qui ont besoin d'accéder ont exactement les mêmes permissions que l'auteur original.

TL; DR?

voilà comment on fait.

nous avons besoin de créer un groupe d'utilisateurs partagé appelé laravel, le groupe se compose de tous les utilisateurs qui ont besoin d'accéder au stockage et aux répertoires bootstrap/cache. Ensuite, nous devons nous assurer que les fichiers et dossiers nouvellement créés ont les permissions laravel group et 664 et 775 respectivement.

il est facile de faire cela pour les fichiers/répertoires existants, mais un peu de magie est nécessaire pour modifier les règles de création de fichier/dossier par défaut...

## 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

purement à des fins de débogage, j'ai trouvé utile de séparer les logs en cli/web + utilisateurs, donc j'ai légèrement modifié la réponse de Sam Wilson. Mon cas d'utilisation était la file d'attente a couru sous son propre utilisateur de sorte qu'il a aidé à faire la distinction entre l'utilisateur compositeur en utilisant le cli (par exemple des tests unitaires) et le démon de file d'attente.

$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);
}); 
7
répondu Andrew 2017-04-30 12:27:17

Laravel 5.1

dans notre cas, nous voulions créer des fichiers journaux pour que tous les processus et les utilisateurs du groupe deploy aient les permissions de lecture/écriture - nous avions donc besoin de nouveaux fichiers créés avec la permission 0664. Par défaut pour les nouveaux fichiers journaux est 0644. Donc c'était notre solution.

nous avons aussi ajouté un formatteur pour ajouter des nouvelles lignes et un log plus lisible

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

il est également possible de combiner cela avec la réponse acceptée

$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);
});
6
répondu Artur Käpp 2015-12-04 09:00:44

Laravel version 5.6.10 et ultérieure a le support pour un permission élément dans la configuration pour le single et le daily pilote:

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

Pas besoin de jongler avec Monolog dans le script bootstrap.

plus précisément, le soutien a été ajouté dans https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8 .

6
répondu crishoj 2018-09-22 17:44:37

j'ai rencontré le même problème sur Laravel 5.6

Dans config/logging.php je viens de mettre à jour quotidienne du canal du chemin d'accès de la valeur avec php_sapi_name() .

cela crée un répertoire séparé pour différents php_sapi_name et met le fichier journal avec l'horodatage dans leur répertoire particulier.

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

Donc, pour moi,

  • les fichiers journaux sont créés sous fpm-fcgi répertoire: Logs du site web, owner: www-data
  • Les fichiers journaux
  • sont créés dans le répertoire cli : à partir de la commande artisan(cronjob). owner: root

plus d'informations sur Laravel 5.6 logging: https://laravel.com/docs/5.6/logging

Voici mon fichier 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
répondu Lahar Shah 2018-03-19 17:47:51

ajoutez quelque chose comme ceci au début de votre fichier app/start/artisan.php (C'est avec 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);
}

ajustez le chemin si le fichier journal que vous mentionnez n'est pas le fichier journal Laravel standard. Vous pouvez aussi ne pas vouloir changer le groupe ou définir les permissions comme je le fais ici. Ce qui précède définit le groupe à www-data et définit les permissions d'écriture du groupe. J'ai ensuite ajouté mon Utilisateur régulier au groupe www-data de sorte que l'exécution des commandes artisan comme mon utilisateur peut toujours écrire dans le journal.

un tweak lié est de mettre ce qui suit Au début de votre app/start/global.php fichier:

umask(0002);

si vous faites cela, la ligne chmod ci-dessus devient sans objet. Avec l'umask défini à ceci, tout nouveau fichier PHP (et donc Laravel) makes aura ses permissions masquées uniquement pour que les "autres" utilisateurs n'aient pas de permissions d'écriture. Cela signifie que les répertoires commenceront par rwxrwxr-x et les fichiers par rw-rw-r-- . Donc si www-data exécute PHP, tous les fichiers de cache et de log qu'il crée seront accessibles en écriture par défaut par n'importe qui dans le groupe principal de cet utilisateur, qui est www-data .

3
répondu tremby 2015-02-25 01:48:07

Laravel 5.5

ajouter ce code à 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);
});
  • il va stocker des fichiers comme ceci: laravel-2018-01-27-cli-raph.log et laravel-2018-01-27-fpm-cgi-raph.log qui est plus lisible.
  • les Nouvelles lignes sont conservées (par défaut Laravel comportement)
  • Il travaille avec Laravel Visionneuse du Journal

Laravel 5.6

You doit créer une classe pour votre 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;
    }
}

ensuite, vous devez l'enregistrer dans config/logging.php :

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

même comportement que pour 5.5:

  • il va stocker des fichiers comme ceci: laravel-2018-01-27-cli-raph.log et laravel-2018-01-27-fpm-cgi-raph.log qui est plus lisible.
  • les Nouvelles lignes sont conservées (par défaut Laravel comportement)
  • il fonctionne avec Laravel Visionneuse Du Journal
3
répondu rap-2-h 2018-02-20 11:14:25

Laravel 5.4

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

ajouter à boot fonction dans AppServiceProvider

2
répondu StupidDev 2017-08-01 03:43:25

une façon non-Laravel de faire ce travail est de simplement exécuter votre cronjob en tant que 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
1
répondu user2662680 2018-06-14 15:45:31

(Laravel 5.6) j'ai récemment rencontré le même problème et j'ai simplement mis une commande programmée à exécuter dans /app/Console/Kernel.php .

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

je sais que c'est un peu exagéré, mais il fonctionne comme un charme et n'ai pas eu de problèmes depuis.

1
répondu Ague Mort 2018-07-26 01:59:03

le meilleur moyen que j'ai trouvé est que fideloper suggère, http://fideloper.com/laravel-log-file-name , vous pouvez configurer laravel log sans toucher à la classe Log. Ont des noms différents pour les programmes de Console et les programmes Http, je pense, est la meilleure solution.

-1
répondu Giacomo 2017-04-04 09:46:54