Uso de la Terminal en PiecesPHP
Introducción
Puedes ejecutar tareas administrativas y de mantenimiento desde la terminal usando el CLI de PiecesPHP. Estas tareas están orientadas a la gestión del framework y requieren permisos de usuario root en el sistema PiecesPHP.
Instrucciones básicas
Desde la raíz del repositorio, ejecuta:
bin/cli es el atajo recomendado: elige el PHP correcto (php8.5 si existe; con PCSPHP_PHP_BIN fijas otro), entra
en src/ y llama a la forma larga añadiendo --local, que el CLI necesita para conectar con la base de datos de
la instalación local. La forma larga equivalente es:
Ojo: el
phpa secas del sistema puede ser anterior al piso del framework (>=8.5 <8.6) y dar resultados que no valen. Usabin/cli.
⚡ Orden de Preferencia
Cuando ejecutas un comando en la terminal, PiecesPHP sigue este orden estricto de resolución:
- Rutas del Sistema: Primero intenta hacer coincidir la acción contra las rutas registradas en el cargador de la aplicación.
- Acciones Personalizadas (
CliActions): Si no hay coincidencia en rutas, busca en las acciones registradas medianteCliActions::make(). - Eventos desacoplados: Si falla lo anterior, dispara el evento
EVENT_CLI_ROUTE_NOT_FOUND_NAME. - Error: Si nada de lo anterior responde, muestra el mensaje de error de terminal.
💻 Autocompletado
PiecesPHP soporta autocompletado nativo para presionar la tecla TAB y descubrir comandos. Esto agiliza la escritura y evita errores en la terminal.
Linux / Mac OS (Bash y Zsh)
Simplemente ejecuta uno de estos comandos según tu shell para registrar el completador (puedes añadir la carga a tu .bashrc o .zshrc):
Windows
Para disfrutar del autocompletado en Windows, la opción recomendada y soportada oficialmente es utilizar Git Bash o WSL (Subsistema de Windows para Linux) y seguir las mismas instrucciones indicadas arriba (usando bin/pieces-completion.bash).
🎨 Salida Inteligente (Salida sin Color)
La clase interna PiecesPHP\Cli detecta automáticamente si el comando está siendo redirigido a un archivo (Ej: bin/cli ... > archivo.txt) o encadenado en un pipe (bin/cli ... | grep ...).
Cuando detecta la tubería, limpia los códigos ISO de colores para evitar que se filtren símbolos de formato ([0m33, etc.) en tus archivos de texto.
Acciones disponibles
Todas, de un vistazo
Medido contra src/app/classes/Terminal/Tasks/ el 2026-10-05 (una acción por archivo de esa carpeta, salvo las
auxiliares abstractas); seed, añadida el 2026-10-08. bin/cli help da la lista de tu versión; bin/cli help task=<acción> filtra por una.
Las acciones de pruebas (unit-tests:…, etc.) las enumera bin/cli gates, no help.
| Acción | Parámetros | Qué hace |
|---|---|---|
db-backup |
gz, data, routines, views, definer (yes/no) |
Respalda la base en dumps/ |
db-restore |
file=<ruta>, confirm=yes, database= |
Restaura un volcado. Destruye los datos de la base destino: exige confirm=yes |
bundle |
app, statics, all, zip (yes/no) |
Empaqueta la app y/o los estáticos en bundle/ |
clean-cache / clean-logs / clean-all |
— | Fuerza que todos descarguen de nuevo los estáticos (renueva la marca global, borra las imágenes optimizadas y los accesos directos de server-delegated que el usuario que la ejecuta pueda borrar) / limpia los logs, sin borrar los archivos del formato viejo de sesiones caducadas / las dos |
scan-missing-lang |
--exclude-lang=, --exclude-group= |
Informe de traducciones faltantes |
scan-invalid-utf8 |
table, limit (def. 5000) |
Busca UTF-8 inválido en columnas de texto. Solo lectura. Córrela antes de desplegar |
run-cronjobs / cronjobs-status |
— | Ejecuta los cronjobs que tocan / muestra franja, último éxito, intentos y último error (solo lectura) |
process-queue |
--limit (def. 60) |
Worker de la cola |
scheme-create |
module=<Nombre>\|all, output= |
Emite el CREATE TABLE de los mappers del módulo, padres antes que hijas. No lo ejecuta |
scheme-drop |
module=<Nombre>\|all, output= |
Emite el DROP TABLE, hijas antes que padres. No lo ejecuta |
seed |
module=<Nombre>\|all, cantidad=<n>, escribir=yes, limpiar=yes |
Siembra datos de prueba en la base local. Sin escribir=yes ni limpiar=yes solo simula; escribir y limpiar van con module=all. Ver Datos de prueba |
verify-integrity |
update-snapshot, list-narrative |
Las comprobaciones estructurales del repositorio (las que lista bin/cli verify-integrity) |
gates |
only=<trozo>, with=external |
Corre todas las suites de pruebas y falla si alguna no corrió. with=external incluye las que salen a la red o envían correo |
snapshot |
label=, compare=a,b, dir= |
Foto de la base y del árbol, y su diferencia |
route-inventory |
output= (def. files/dev/route-inventory.json) |
Vuelca en JSON las rutas registradas. Solo lectura |
generate-app-key |
— | Imprime una app_key nueva para pegarla en config.php. No escribe nada |
sync-otp-records |
apply=yes |
Crea los registros OTP que falten. Sin apply=yes solo informa |
statics-protect-migrate |
--dry-run (def.), --run, --revert |
Aplica a uploads/ la protección por sufijo (ver Archivos protegidos) |
repair-escaped-text |
apply=yes |
Deshace una vez el escape que piecesphp/database 4 guardaba en el texto. Sin apply=yes solo cuenta; para aplicar exige un volcado de la última hora |
fix-webm-duration |
--updir=, --glob=, --force… |
Repara la duración interna de archivos WebM con FFmpeg |
db-backup-rotate |
apply (yes/no, def. no), dir= (solo pruebas) |
Aplica la conservación de respaldos de la política: sin apply=yes enseña qué se conserva y qué se borraría |
mail-doctor |
horas=<n>, smtp=yes |
Dice si el correo puede salir de la instalación y por dónde. No envía nada. Sin smtp=yes no toca la red; con él abre una conexión al SMTP configurado y la corta sin enviar |
mail-demo |
— | Manda un correo de cada plantilla del catálogo a la bandeja de pruebas. Solo en una instalación local y solo si la entrega efectiva es «Retenido»; si no, se niega |
organizations-assign-codes |
— | Pone el código público a las organizaciones que no lo tienen. Idempotente |
profiles-create-missing |
confirm=yes |
Enumera los usuarios cuyo tipo lleva perfil y no lo tienen; con confirm=yes, se lo crea a cada uno. Para correrla una vez al actualizar desde una versión que los creaba en cada petición |
system-alerts |
— | Enumera los avisos del sistema activos, con su gravedad y si están ocultos. Solo lectura |
version |
— | Imprime la versión de la instalación, su fecha y el commit del que salió, con su fuente |
version-stamp |
commit=<40 hex> |
Escribe el sello de despliegue con el commit, para instalaciones sin .git. Sale con 1 si el hash no es válido o no hay ninguno |
clone-compare |
ruta=, framework=, contra=, salida=, detalle=yes |
Compara un proyecto hecho a partir del framework con el framework, archivo por archivo, y dice de qué versión partió. Solo lectura. Ver 10. clone-compare |
clean-test-configs |
apply=yes, key=<nombre> |
Retira las configuraciones de prueba (las que empiezan por el prefijo de prueba). Sin apply=yes solo las enumera |
settings-migrate-extra-scripts |
— | Pasa los «Scripts adicionales» de Identidad y SEO a la pantalla «Scripts» y retira las opciones viejas. Se puede repetir: la segunda vez no hace nada |
sessions-revoke-all |
confirm=yes |
Cierra las sesiones de todos los usuarios. Exige confirm=yes |
data-transfer-import |
definition=, file=, as-user=, credentials-out=, dry-run=yes |
Importa un .xlsx o .csv con un importador registrado; todo o nada. Con dry-run=yes valida sin guardar |
help |
task=<acción> |
Lista las acciones disponibles (o solo la indicada) |
Las que siguen se detallan con ejemplo.
1. db-backup
Respalda la base de datos por defecto.
Parámetros:
gz(yes|no) — Define si el respaldo se comprime en gzip. Por defecto: yes.data(yes|no) — Incluir datos de las tablas (registros). Por defecto: yes.routines(yes|no) — Incluir rutinas guardadas (funciones y procedimientos). Por defecto: yes.views(yes|no) — Incluir la estructura de vistas de BD. Por defecto: yes.definer(yes|no) — Incluir la etiqueta de DEFINER de MySQL/MariaDB en las sentencias de los objetos. Por defecto: no.
Ejemplo:
Restaurar: bin/cli db-restore file=<volcado.sql> confirm=yes (ver la tabla de abajo).
AVISO — copias anteriores a esta versión NO restauran las contraseñas. La base restaurada dejaría a todos los usuarios sin poder entrar. Si necesitas restaurar una copia de ese tipo, pide el procedimiento de recuperación a quien mantiene el framework.
2. bundle
Empaqueta la aplicación y/o los archivos estáticos.
Parámetros:
-
app(yes|no) — Solo carpeta app. Por defecto: no -
statics(yes|no) — Solo carpeta statics (sin filemanager, uploads ni plugins). Por defecto: no -
all(yes|no) — app y statics. Por defecto: no -
zip(yes|no) — Define si solo copia los archivos o los comprime como zip. Por defecto: no
Ejemplo:
3. clean-cache
Fuerza la limpieza de caché de archivos estáticos mediante la renovación del token.
Parámetros:
- N/A
Ejemplo:
4. clean-logs
Limpia los archivos de logs: errores, deprecaciones, logs antiguos, anotaciones de traducciones faltantes y el
registro de sesiones caducadas (app/logs/expired-sessions.log y su rotado).
No borra los .json del formato viejo de app/logs/expired-sessions/: los cuenta y avisa de que
contienen datos de sesión, para que usted decida. La carpeta se retira sola cuando queda vacía. (Hasta la v8.0.0 sí los
borraba; ver el CHANGELOG.)
Parámetros:
- N/A
Ejemplo:
5. clean-all
Limpia caché y logs en una sola acción.
Parámetros:
- N/A
Ejemplo:
6. scan-missing-lang
Revisa los mensajes faltantes por traducción y genera un archivo con ellos.
Parámetros:
-
--exclude-lang— Cadena separada por comas de idiomas a ignorar. Ejemplo:--exclude-lang=es,en -
--exclude-group— Cadena separada por comas de grupos a ignorar. Ejemplo:--exclude-group=general,public
Ejemplo:
7. run-cronjobs
Ejecuta todas las tareas programadas (CronJobs) que cumplan su condición de tiempo en el momento de la ejecución.
Parámetros:
- N/A
Ejemplo:
8. process-queue
Procesa las tareas pendientes en la cola de ejecución (tabla pcsphp_jobs_queue). Utiliza un sistema de bloqueos (locks) para evitar ejecuciones paralelas excesivas, y cada trabajo lo toma un solo trabajador: se marca «en ejecución» con una actualización condicional y, si otro trabajador se adelantó, se salta. Lo terminado de más de 30 días y lo fallido de más de 90 lo borra la tarea diaria «Purgar registros viejos».
Parámetros:
--limit(int) — Cantidad máxima de tareas a procesar en esta ejecución. Por defecto: 60.
Ejemplo:
9. help
Muestra la lista de tareas disponibles y su descripción.
Ejemplo:
El atajo h se retiró en la 8.0.0.
10. clone-compare
Compara un proyecto que nació de PiecesPHP con el framework, archivo por archivo, para saber de qué versión partió y qué cambió. Sirve para preparar la actualización de un proyecto antiguo. Solo lee: no escribe en el proyecto ni en el framework, y nunca enseña el contenido de un archivo, solo rutas y cifras (un proyecto tiene configuración y claves).
Se ejecuta desde un repositorio git del framework con sus etiquetas (las versiones v*) y apunta a la raíz del proyecto:
bin/cli clone-compare ruta=/var/www/html/mi-proyecto
bin/cli clone-compare ruta=/var/www/html/mi-proyecto salida=/home/yo/comparacion.json detalle=yes
bin/cli clone-compare ruta=/var/www/html/mi-proyecto contra=v10.0.0
| Parámetro | Qué hace |
|---|---|
ruta= |
La raíz del proyecto (obligatorio) |
framework= |
La raíz del repositorio git del framework. Por omisión, el de esta instalación |
contra= |
La versión contra la que se compara. Por omisión, la «más parecida» (abajo) |
salida= |
Un archivo .json con el informe completo. No puede estar dentro del proyecto |
detalle=yes |
Lista en pantalla las rutas de cada grupo; sin él, solo las cifras |
De qué versión partió. Da dos respuestas, porque un proyecto que se actualizó a mano copiando archivos no tiene una sola:
- nacimiento: la versión con la que comparte más rutas (los mismos archivos, aunque cambiaran). Es la versión de la que nació. Si varias versiones tienen el mismo árbol de archivos, empatan, y el informe lo dice;
- más parecida: la versión con más archivos idénticos. Es de la que más copió, y contra la que se compara si no das
contra=.
Además, para cada archivo dice la versión más reciente que lo tiene idéntico (o ninguna, si es propio del proyecto o lo cambió), y cuántos archivos hay de cada versión. Un archivo que no cambió en años sale con la última versión que lo conserva igual, no con la que se copió.
Los grupos. Cada archivo del proyecto y de la versión comparada cae en uno:
| Grupo | Qué significa |
|---|---|
igual |
El mismo contenido (los finales de línea de Windows no cuentan) |
igual-nivel-1 |
Igual salvo espacios al final de las líneas o líneas en blanco al final del archivo |
igual-nivel-2 |
Solo PHP: igual salvo comentarios y espacios |
modificado |
Cambió |
solo-framework |
Está en el framework y no en el proyecto (borrado, renombrado o nuevo después) |
solo-framework-no-viaja |
Lo mismo, pero el framework no lo entrega a los proyectos: no le falta nada |
solo-proyecto |
Es del proyecto, o un archivo del framework que se movió de sitio |
En pantalla salen las dos respuestas, el resumen, los diez módulos con más cambios y las cinco versiones de las que más archivos conserva. El JSON trae además la lista de rutas de cada grupo, el reparto por módulo y la versión de cada archivo.
Lo que no ve
- Si el proyecto es un repositorio git, solo mira lo versionado y lo nuevo que su
.gitignoreno ignora; si no lo es, todo el disco. Nunca mira las dependencias (src/vendor,node_modules), las cachés, los registros, las subidas, los respaldos nisecure-keys/. - Un archivo movido de carpeta sale dos veces: en
solo-proyectoy ensolo-framework. - Que un archivo sea idéntico a una versión no dice quién lo copió de quién: a veces el framework tomó código de un proyecto.
- No lee
.gitattributes: un archivo que tu proyecto guarda con otros finales de línea a propósito puede salir enigual-nivel-1aunque sea igual. - Lo que no se puede leer por permisos sale aparte (
ilegiblesen el JSON) y no cuenta en ningún grupo. - Cada archivo se lee entero: uno enorme fuera de las carpetas excluidas puede agotar la memoria de PHP.
Programación de Tareas (Desarrollo)
CronJobs
Las tareas se definen usando la clase PiecesPHP\Terminal\CronJobTask y se registran típicamente en src/app/config/extensions/cronjobs.php.
Ejemplo de definición:
CronJobTask::make('Limpieza diaria', function() {
// Lógica de la tarea
return ['success' => true, 'message' => 'Limpieza completada'];
})->dailyAt("03:00")->addCronJob();
Colas (Queues)
El sistema de colas permite ejecutar procesos pesados de forma asíncrona.
-
Definir Handler: Registrado en
src/app/config/extensions/queues.php. -
Despachar Tarea: Desde cualquier parte de la aplicación.
-
Ejecución: la drena cada minuto el cronjob del sistema «Procesar la cola» (
src/app/core/extensions/cronjobs.php), con la única línea decrontabde la instalación (ver CronJobs). No hace falta otra. A mano:bin/cli process-queue. Dos ejecuciones a la vez no procesan el mismo trabajo, y un proceso muerto a mitad no atasca la cola: el trabajo que lleva más de 30 minutos enrunningvuelve apendingen la siguiente pasada, o afailedsi ya agotó sus intentos (ver Colas).
🛠️ Acciones CLI Personalizadas (Custom Actions)
PiecesPHP permite registrar tus propias acciones de terminal mediante la clase PiecesPHP\Terminal\CliActions. Esto es ideal para integrar scripts de mantenimiento, migraciones o motores reactivos.
Registro de una acción
Típicamente se definen en src/app/config/extensions/cli-actions.php:
use PiecesPHP\Terminal\CliActions;
use React\EventLoop\Loop;
// Ejemplo de un loop reactivo (ReactPHP)
CliActions::make('mi-motor', function ($args) {
echoTerminal("Iniciando motor reactivo...");
Loop::addPeriodicTimer(1.0, function () {
echoTerminal("Revisando tareas...");
});
Loop::run();
})->setDescription('Ejecuta un motor reactivo')->register();
Ejecutar Acción
El framework primero prefiere las acciones mediante el sistema de rutas. Pero si no se encuentra la acción, buscará en las acciones personalizadas (cli-actions).
Notas y advertencias
- Algunas tareas requieren permisos de usuario root PiecesPHP.
- Los respaldos de base de datos se guardan en la carpeta
dumpsy los bundles en la carpetabundle. - Los parámetros pueden ser escritos en mayúsculas o minúsculas, pero se recomienda usar minúsculas.
- Si tienes dudas sobre los parámetros de una acción, ejecuta
bin/cli help.