Dzienny dziennik Laravel utworzony z błędnymi uprawnieniami

Mam skrypt, który uruchamiam przy użyciu PHP artisan( z root user), i czasami powoduje, że dzienny plik dziennika jest tworzony przed Apache www-data User robi - co oznacza, że gdy prawdziwy użytkownik korzysta z mojej aplikacji internetowej, dostaję błąd uprawnień folderu:

Nie udało się otworzyć strumienia: Odmowa uprawnień

Zmieniam uprawnienia z powrotem na www-data za każdym razem, ale chcę to rozwiązać, mając plik dziennika zawsze utworzony z popraw uprawnienia.

Rozważałem stworzenie Zadania cron, które tworzy plik lub dotyka go, aby upewnić się, że ma odpowiednie uprawnienia każdego dnia, ale szukam lepszego rozwiązania, które nie opiera się na innym skrypcie.

Rozważaliśmy również owinięcie PHP artisan w inny skrypt, aby upewnić się, że jest on zawsze uruchamiany z poświadczeniami www-data , ale niektóre rzeczy, które chcemy zrobić, są w rzeczywistości root procedurami, na które apache nie powinien mieć pozwolenia.

Jeszcze jakieś sugestie?

Author: Moshe Katz, 2014-12-28

13 answers

Zacznijmy od tego, co jest stałe.

Masz php artisan polecenie, uruchamiane przez root.

Można bezpiecznie założyć, że polecenie to jest wykonywane codziennie.

Roztwór No 1:

Biorąc pod uwagę, że użytkownik, który tworzy pliki, Jest Tym, który ma prawo do zapisu do niego domyślnie, możemy oddzielić logi według użytkownika jako takie:

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

Jeśli twój użytkownik www-data utworzy dziennik błędów, spowoduje to: storage/logs/laravel-www-data-2015-4-27.log.

Jeśli twój użytkownik root utworzy dziennik błędów, spowoduje to: storage/logs/laravel-root-2015-4-27.log.

Roztwór No 2:

Zmień dziennik używany przez komendę artisan w skrypcie php.

W funkcji run() Dodaj tę linię na początku:

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

Jeśli nazwa twojej klasy to ArtisanRunner, Twój plik dziennika będzie wyglądał następująco:

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

Wniosek: rozwiązanie numer 1 jest lepsze, biorąc pod uwagę, że określa twoje logi przez użytkownika, i dlatego nie będzie żadnych błędów.

EDIT: jak zauważył jason, get_current_user() zwraca nazwę właściciela skryptu. Dlatego, aby zastosować rozwiązanie nr 1, chown Twoje pliki klasy artisan do wymaganej nazwy użytkownika.

 50
Author: Mysteryos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 16:34:35

Dla Laravel 5.1 używam poniższego do dołu bootstrap/app.php (Jak wspomniano w 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);
});

Istnieje wiele innych programów obsługi, które możesz użyć zamiast tego, oczywiście.

 57
Author: Sam Wilson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-22 04:39:33

Do takich celów powinieneś używać advanced ACL na swoich plikach i katalogach. setfacl to będzie twoja odpowiedź tutaj. Jeśli chcesz nadać www-data uprawnienia użytkownika do zapisu na plikach roota w określonym katalogu, możesz to zrobić w następujący sposób:

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

Po jej wydaniu ustawiasz uprawnienia rwx dla www-data user na wszystkich plikach w /my/folder/ bez względu na to, kto je stworzył. Proszę, Zobacz to i to pytanie w celach informacyjnych. Ponadto możesz sprawdź dokumenty dla setfacl.

Daj mi znać, jeśli to pomoże.
 19
Author: Paul Tomkiel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 12:36:31

Dla mnie ten problem był czymś więcej niż tylko uprawnieniami do logowania...Miałem problemy z czymś związanym z folderami bootstrap / cache i storage, w których jeden użytkownik utworzy plik / folder, a drugi nie będzie mógł edytować / usuwać ze względu na standardowe uprawnienia 644 i 755.

Typowe scenariusze to:

  • Bootstrap/cache / compiled.plik php jest tworzony przez użytkownika apache, ale jest nieedytowalny przez użytkownika composer podczas wykonywania composer install polecenia

  • Użytkownik apache tworzy pamięć podręczną, której nie można wyczyścić za pomocą użytkownika composer

  • opisane powyżej przerażające warunki rasy logów.

Marzeniem jest to, że bez względu na to, który użytkownik utworzy plik / folder, inni użytkownicy, do których należy uzyskać dostęp, mają dokładnie takie same prawa jak oryginalny autor.

TL; DR?

Oto jak to się robi.

Musimy utworzyć wspólną grupę użytkowników o nazwie laravel, grupa składa się ze wszystkich użytkownicy, którzy potrzebują dostępu do katalogów storage i bootstrap/cache. Następnie musimy upewnić się, że nowo utworzone pliki i foldery mają odpowiednio uprawnienia laravel group oraz 664 i 775.

Jest to łatwe dla istniejących plików / katalogów, ale potrzeba trochę magii, aby dostosować domyślne reguły tworzenia plików / folderów...

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

Czysto w celach debugowania stwierdziłem, że podział logów na obu użytkowników cli/web + był korzystny, więc zmodyfikowałem odpowiedź sama Wilsona trochę. Mój przypadek użycia polegał na tym, że kolejka działała pod własnym użytkownikiem, więc pomogła odróżnić użytkownika composera używającego cli (np. testów jednostkowych) od demona kolejki.

$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
Author: Andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-30 12:27:17

Laravel 5.1

W naszym przypadku chcieliśmy utworzyć pliki logów tak, aby wszystkie procesy i użytkownicy w grupie deploy mieli uprawnienia do odczytu/zapisu - więc potrzebowaliśmy nowych utworzonych plików z uprawnieniem 0664. Domyślnie dla nowych plików dziennika jest 0644. Więc to było nasze rozwiązanie.

Dodaliśmy również formatator do dodawania nowych linii i bardziej czytelnego dziennika

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

Możliwe jest również połączenie tego z zaakceptowaną odpowiedzią

$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
Author: Artur Käpp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-04 09:00:44

Laravel w wersji 5.6.10 i nowszej posiada wsparcie dla elementu permission w konfiguracji dla Sterownika single i daily:

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

Nie trzeba żonglować monologiem w skrypcie bootstrap.

W szczególności wsparcie zostało dodane w https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8 .

 6
Author: crishoj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-22 17:44:37

Natknąłem się na ten sam problem na Laravel 5.6

W tym przypadku nie jest to możliwe.

Tworzy osobny katalog dla różnych nazw php_sapi_name i umieszcza plik dziennika ze znacznikiem czasu w ich perticular directory.

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

Więc dla mnie,

    Pliki logów są tworzone w katalogu fpm-fcgi: Logs from website, owner: www-data
  • pliki logów są tworzone w katalogu cli: from the artisan dowództwo (cronjob). owner: root

Więcej informacji o logowaniu Laravel 5.6: https://laravel.com/docs/5.6/logging

Oto Mój config/logging.php Plik:

<?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
Author: Lahar Shah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 17:47:51

Dodaj coś podobnego do poniższego na początku pliku app/start/artisan.php (jest to z 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);
}

Dostosuj ścieżkę, jeśli dzienny plik dziennika, o którym wspominasz, nie jest standardowym plikiem dziennika Laravela. Możesz również nie chcieć zmieniać grupy lub ustawiać uprawnień, tak jak to robię tutaj. Powyższe ustawia grupę na www-data i ustawia uprawnienia do zapisu grupy. Następnie dodałem mojego zwykłego użytkownika do grupy www-data, aby uruchamiając polecenia artisan jako mój zwykły użytkownik mógł nadal pisać do log.

Powiązaną poprawką jest umieszczenie na początku pliku app/start/global.php następującej treści:

umask(0002);

Jeśli to zrobisz, chmod linia powyżej staje się dyskusyjna. Z ustawioną na to umask, wszystkie nowe pliki PHP (a więc Laravel) będą miały zamaskowane uprawnienia tylko tak ,że "inni" użytkownicy nie będą mieli uprawnień do zapisu. Oznacza to, że katalogi będą zaczynać się jako rwxrwxr-x, a pliki jako rw-rw-r--. Więc jeśli {[3] } jest uruchomiony PHP, wszelkie pliki pamięci podręcznej i logów, które tworzy, będą domyślnie zapisywane przez każdego w główna grupa tego użytkownika, czyli www-data.

 3
Author: tremby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-25 01:48:07

Laravel 5.5

Dodaj ten kod do 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);
});
  • będzie przechowywać pliki takie jak: laravel-2018-01-27-cli-raph.log i laravel-2018-01-27-fpm-cgi-raph.log, które są bardziej czytelne.
  • nowe linie są zachowywane (od domyślnego zachowania Laravela)
  • To działa z Laravel Log Viewer

Laravel 5.6

Ty musisz utworzyć klasę dla swojego loggera:

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

Następnie musisz go zarejestrować w config/logging.php:

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

Takie samo zachowanie jak dla 5.5:

  • będzie przechowywać pliki takie jak: laravel-2018-01-27-cli-raph.log i laravel-2018-01-27-fpm-cgi-raph.log, które są bardziej czytelne.
  • nowe linie są zachowywane (od domyślnego zachowania Laravela)
  • To działa z Laravel Log Viewer
 3
Author: rap-2-h,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-20 11:14:25

Laravel 5.4

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

Dodaj do boot funkcji w AppServiceProvider

 2
Author: StupidDev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-01 03:43:25

Jednym Nie-Laravelowym sposobem na wykonanie tej pracy jest po prostu wykonanie pracy cronjob jako 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
Author: user2662680,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-14 15:45:31

(Laravel 5.6) ostatnio napotkałem ten sam problem i po prostu ustawiłem zaplanowane polecenie do uruchomienia w /app/Console/Kernel.php.

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

Wiem, że to trochę przesada, ale działa jak urok i od tamtej pory nie miałem żadnych problemów.
 1
Author: Ague Mort,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-26 01:59:03

Najlepszy sposób znalazłem to to, że fideloper zasugerował, http://fideloper.com/laravel-log-file-name , możesz ustawić konfigurację dziennika laravel bez klasy touch Log. Mają różne nazwy dla programów konsolowych i programów Http, myślę, że jest to najlepsze rozwiązanie.

 -1
Author: Giacomo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-04 09:46:54