laravel 4 - tabla - Registro diario de Laravel creado con permisos incorrectos
login personalizado laravel (15)
Laravel 5.8
Laravel 5.8 le permite configurar el nombre de registro en
config/logging.php
.
Entonces, utilizando respuestas y comentarios anteriores, si desea nombrar, inicie sesión con el nombre de usuario posix real Y el valor
php_sapi_name()
, solo necesita cambiar el conjunto de nombres de registro.
El uso del controlador diario permite la rotación de registros que se ejecuta por combinación de usuario / API, lo que garantizará que el registro sea rotado siempre por una cuenta que pueda modificar los registros.
También agregué una verificación para las funciones posix que pueden no existir en su entorno local, en cuyo caso el nombre de registro simplemente se ajusta al estándar.
Suponiendo que está utilizando el canal de registro predeterminado ''diario'', puede modificar su clave ''canales'' de la siguiente manera:
# 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,
],
...
Esto dará como resultado un nombre de registro que debería ser exclusivo para cada combinación, como
laravel-cli-sfscs-2019-05-15.log
o
laravel-apache2handler-apache-2019-05-15.log
dependiendo de su punto de acceso.
Tengo un script que ejecuto usando php artisan (con usuario root ), y a veces hace que el archivo de registro diario se cree antes que el usuario apache www-data, lo que significa que cuando un usuario real usa mi aplicación web, obtengo el error de permiso de carpeta:
Error al abrir la transmisión: permiso denegado
Vuelvo a cambiar los permisos a www-data cada vez, pero quiero resolver esto haciendo que el archivo de registro siempre se cree con los permisos correctos.
He considerado crear un trabajo cron que cree el archivo o lo toque para asegurarme de que tenga el permiso correcto todos los días, pero estoy buscando una mejor solución que no se base en otro script.
También hemos considerado incluir php artisan en otro script para asegurarnos de que siempre se ejecute con las credenciales de www-data , pero algunas cosas que queremos hacer son en realidad procedimientos raíz que apache no debería poder hacer.
¿Alguna sugerencia más?
Tenía esto funcionó de manera muy simple:
Me encontré con el mismo problema en Laravel 5.6
En
config/logging.php
, acabo de actualizar el valor de la ruta del canal diario con
php_sapi_name()
en él.
Esto crea un directorio separado para diferentes php_sapi_name y coloca el archivo de registro con la marca de tiempo en su directorio particular.
''daily'' => [
''driver'' => ''daily'',
''path'' => storage_path(''logs/'' . php_sapi_name() . ''/laravel.log''),
''level'' => ''debug'',
''days'' => 7,
]
Entonces para mi
-
Los archivos de registro se crean en el directorio
fpm-fcgi
: registros del sitio web,owner: www-data
-
Los archivos de registro se crean en el directorio
cli
: desde el comando artesanal (cronjob).owner: root
Más información sobre el registro de Laravel 5.6: https://laravel.com/docs/5.6/logging
Aquí está mi archivo
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.5
Agregue este código a
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);
});
-
Almacenará archivos como este:
laravel-2018-01-27-cli-raph.log
ylaravel-2018-01-27-fpm-cgi-raph.log
que es más legible. - Se conservan nuevas líneas (como comportamiento predeterminado de Laravel)
- Funciona con Laravel Log Viewer
Laravel 5.6
Tienes que crear una clase para tu registrador:
<?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;
}
}
Luego, debe registrarlo en
config/logging.php
:
''channels'' => [
''custom'' => [
''driver'' => ''custom'',
''via'' => App/Logging/CreateCustomLogger::class,
],
],
Mismo comportamiento que para 5.5:
-
Almacenará archivos como este:
laravel-2018-01-27-cli-raph.log
ylaravel-2018-01-27-fpm-cgi-raph.log
que es más legible. - Se conservan nuevas líneas (como comportamiento predeterminado de Laravel)
- Funciona con Laravel Log Viewer
(Laravel 5.6) Recientemente me encontré con el mismo problema y simplemente configuré un comando programado para ejecutarse en
/app/Console/Kernel.php
.
$schedule->exec(''chown -R www-data:www-data /var/www/**********/storage/logs'')->everyMinute();
Sé que es un poco exagerado, pero funciona de maravilla y no he tenido ningún problema desde entonces.
Agregue algo como lo siguiente al inicio de su archivo
app/start/artisan.php
(esto es con 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);
}
Ajuste la ruta si el archivo de registro diario que menciona no es el archivo de registro estándar de Laravel.
También es posible que no desee cambiar el grupo o establecer los permisos como lo estoy haciendo aquí.
Lo anterior establece el grupo en
www-data
y establece los permisos de escritura del grupo.
Luego agregué mi usuario habitual al grupo
www-data
para que ejecutar comandos artesanales como mi usuario habitual aún pueda escribir en el registro.
Un ajuste relacionado es poner lo siguiente al comienzo de su archivo
app/start/global.php
:
umask(0002);
Si haces esto, la línea de
chmod
de arriba se vuelve discutible.
Con el umask configurado para esto, cualquier archivo nuevo que PHP (y, por lo tanto, Laravel) crea tendrá sus permisos enmascarados solo para que "otros" usuarios no tengan permisos de escritura.
Esto significa que los directorios comenzarán como
rwxrwxr-x
y los archivos como
rw-rw-r--
.
Entonces, si
www-data
está ejecutando PHP, cualquier caché y archivos de registro que haga podrán ser escritos de manera predeterminada por cualquiera en el grupo principal de ese usuario, que es
www-data
.
Comencemos con lo que es constante.
Tienes un comando
php artisan
, ejecutado por
root
.
Es seguro asumir que este comando se ejecuta diariamente.
Solución no 1:
Dado que el usuario que crea los archivos es el que tiene permiso para escribir en ellos de manera predeterminada, podemos separar los registros por usuario como tal:
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 su usuario de
www-data
creara un registro de errores, resultaría en:
storage/logs/laravel-www-data-2015-4-27.log
.
Si su usuario
root
creara un registro de errores, se obtendría:
storage/logs/laravel-root-2015-4-27.log
.
Solución no 2:
Cambie el registro utilizado por su comando artesanal, en su script php.
En su función
run()
, agregue esta línea al comienzo:
Log::useFiles(storage_path().''/logs/laravel-''.__CLASS__.''-''.Carbon::now()->format(''Y-m-d'').''.log'');
Si el nombre de su clase es
ArtisanRunner
, su archivo de registro será:
storage/logs/laravel-ArtisanRunner-2015-4-27.log
.
Conclusión: la solución número 1 es mejor, dado que delimita sus registros por usuario y, por lo tanto, no se producirán errores.
EDITAR: como señaló jason,
get_current_user()
devuelve el nombre del propietario del script.
Por lo tanto, para que se aplique la solución n. ° 1,
chown
sus archivos de clase artesanal al nombre de usuario requerido.
La mejor manera que encontré es que fideloper sugiere, http://fideloper.com/laravel-log-file-name , puede establecer la configuración de registro de laravel sin tocar la clase Log. Tener diferentes nombres para programas de consola y programas Http, creo, es la mejor solución.
Laravel 5.4
/Log::getMonolog()->popHandler(); /Log::useDailyFiles(storage_path(''/logs/laravel-'').get_current_user().''.log'');
agregar a la función de
boot
en
AppServiceProvider
Laravel versión 5.6.10 y posterior tiene soporte para un elemento de
permission
en la configuración (
config/logging.php
) para el controlador
single
y el controlador
daily
:
''daily'' => [
''driver'' => ''daily'',
''path'' => storage_path(''logs/laravel.log''),
''level'' => ''debug'',
''days'' => 7,
''permission'' => 0664,
],
No es necesario hacer malabarismos con Monolog en el script de arranque.
Específicamente, se agregó soporte en https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8 .
Para Laravel 5.1, uso lo siguiente hacia la parte inferior de
bootstrap/app.php
(como se menciona en
los documentos
):
/**
* 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);
});
Hay muchos otros controladores que puede utilizar en su lugar, por supuesto.
Para mí, este problema era mucho más que permisos de registro ... Tuve problemas con cualquier cosa relacionada con el bootstrap / caché y las carpetas de almacenamiento donde un usuario crearía un archivo / carpeta y el otro no podría editar / eliminar debido al estándar 644 y 755 permisos.
Los escenarios típicos son:
-
El archivo bootstrap / cache / compiled.php que está creando el usuario de apache pero que el usuario del compositor no puede editar cuando ejecuta el comando de instalación del compositor
-
El usuario apache que crea caché que no se puede borrar usando el usuario compositor
- Las temidas condiciones de carrera de troncos descritas anteriormente.
El sueño es que no importa qué usuario cree el archivo / carpeta, los otros usuarios que necesitan acceder tienen exactamente los mismos permisos que el autor original.
TL; DR?
Así es como se hace.
Necesitamos crear un grupo de usuarios compartido llamado laravel, el grupo está formado por todos los usuarios que necesitan acceso a los directorios de almacenamiento y bootstrap / cache. A continuación, debemos asegurarnos de que los archivos y carpetas recién creados tengan el grupo laravel y los permisos 664 y 775 respectivamente.
Es fácil hacer esto para los archivos / directorios existentes, pero se necesita un poco de magia para ajustar las reglas de creación de archivos / carpetas predeterminadas ...
## 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
Solo para fines de depuración, encontré que dividir los registros en ambos usuarios cli / web + fue beneficioso, así que modifiqué ligeramente la respuesta de Sam Wilson. Mi caso de uso fue que la cola se ejecutó bajo su propio usuario, por lo que ayudó a distinguir entre el usuario del compositor que usaba el cli (por ejemplo, pruebas unitarias) y el demonio de cola.
$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);
});
Para tales fines, debe usar ACL avanzado en sus archivos y directorios.
setfacl
sería tu respuesta aquí.
Si desea otorgar permisos de usuario de
www-data
para escribir en
los
archivos
raíz
en un directorio específico, puede hacerlo así:
setfacl -d -m default:www-data:you-chosen-group:rwx /my/folder
Después de emitir esto, está configurando permisos para
rwx
para el usuario de
www-data
en todos los archivos en
/my/folder/
sin importar quién los haya creado.
Por favor, vea
this
y
esta pregunta
como referencia.
Además, puede consultar
documentos para
setfacl
.
Déjeme saber si esto ayuda.
Simplemente puede cambiar el permiso del archivo de registro en su comando artesanal:
$path = storage_path(''log/daily.log'');
chown($path, get_current_user());
donde get_current_user() devolverá al usuario del script actual.
En otras palabras,
daily.log
siempre tendrá
www-data
como propietario, incluso si inicializa el script como usuario
root
.
Una forma que no es de Laravel para hacer que esto funcione es simplemente ejecutar su cronjob como www-data.
por ejemplo, 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.1
En nuestro caso, queríamos crear todos los archivos de registro para que todo en el grupo de
deploy
tuviera permisos de lectura / escritura.
Por lo tanto, necesitábamos crear todos los archivos nuevos con permisos
0664
, en oposición al
0644
predeterminado
0644
.
También agregamos un formateador para agregar nuevas líneas para una mejor legibilidad:
$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);
});
También es posible combinar esto con la respuesta aceptada
$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);
});