WP-CLI para quienes viven en la terminal
Comandos de WP-CLI para migraciones de WordPress, copias de seguridad, bloqueos, actualizaciones de plugins y core, SSH remoto y search-replace seguro.
WP-CLI es la interfaz de línea de comandos de una instalación de WordPress. Ahorra clics, pero la verdadera razón para aprenderla es el conjunto de tareas para las que el escritorio no tiene ninguna pantalla: reescribir datos serializados de opciones durante un cambio de dominio, ejecutar PHP arbitrario contra un sitio en producción y actualizar diez instalaciones desde un único prompt.
La mayoría de la gente se topa con ella en una emergencia. La actualización de un plugin tumba el administrador, el escritorio no carga y, de repente, FTP más phpMyAdmin es la única vía de vuelta. Esa ruta funciona, pero es lenta y hay que tener cierto temple.
Este artículo está organizado por tarea, no por espacio de nombres. Cada sección es una tarea dolorosa o imposible en el escritorio, seguida del comando que la resuelve y de los flags que la hacen segura.
Puntos clave
wp search-replacedeserializa datos PHP, aplica el reemplazo y vuelve a serializar, y por eso puede reescribir configuraciones de widgets y opciones de plugins que unREPLACE()de SQL puro corrompería.- Ejecuta cada reemplazo primero con
--dry-runy después lanza el comando idéntico sin el flag. - Excluye la columna
guidcon--skip-columns=guid, porque los lectores de feeds usan el guid de una entrada para determinar si ya la han mostrado. --ssh=[<scheme>:][<user>@]<host>[:<port>][<path>]envía un comando a una instalación remota, y la máquina remota necesita su propia copia de WP-CLI que responda awp.- Ninguno de estos comandos pide confirmación ni se puede deshacer, así que
wp db exportva primero.
Estos comandos se ejecutan de inmediato
No hay diálogo de confirmación, ni pantalla de vista previa, ni deshacer. wp search-replace escribe en todas las filas coincidentes en el momento en que pulsas intro. wp plugin deactivate --all desactiva todo en un sitio de producción con la misma facilidad que en un portátil. El único rollback del que dispones es la exportación de la base de datos que hiciste antes, así que hazla.
¿Cómo cambiar un dominio sin romper los datos serializados?
wp search-replace es la herramienta adecuada para un cambio de dominio: lee correctamente el PHP serializado y no toca las claves primarias, dos cosas que un find-and-replace de SQL plano no logra. La razón está en el formato de almacenamiento: la función serialize() de PHP registra una cadena como su longitud en bytes seguida de la cadena misma.
a:1:{s:3:"url";s:27:"https://staging.example.com";}
Un UPDATE ... REPLACE() de SQL a ciegas reescribe la URL a https://example.com y deja el 27 intacto. La longitud declarada ya no coincide con el contenido, PHP ya no puede deserializar el valor y el widget o la opción del plugin que vivía ahí revierte silenciosamente a nada. WP-CLI deserializa la estructura, reemplaza dentro de ella y vuelve a serializar con las longitudes correctas.
Escala en tres pasos:
# 1. report what would change; writes nothing
wp search-replace 'https://staging.example.com' 'https://example.com' \
--skip-columns=guid --dry-run
# 2. optional: write the result to a SQL file instead of the database
wp search-replace 'https://staging.example.com' 'https://example.com' \
--skip-columns=guid --export=migration.sql
# 3. apply it
wp search-replace 'https://staging.example.com' 'https://example.com' \
--skip-columns=guid
--dry-run ejecuta el trabajo completo e imprime el informe, y luego descarta los cambios. --export envía el resultado a un archivo SQL y deja intacta la base de datos en producción, de modo que puedes leer el diff o aplicarlo en otro sitio. Omite la columna guid porque WordPress trata el guid de una entrada como fijo durante toda la vida de la entrada: cámbialo y los lectores de feeds podrían mostrar todo tu histórico como nuevo.
Para datos anidados problemáticos, añade --precise. Por defecto, el comando usa consultas SQL rápidas y cambia automáticamente a PHP para las columnas que contienen datos serializados; --precise fuerza PHP en todas las columnas, lo que es más lento pero más fiable frente a estructuras serializadas complejas. El modo regex también es bastante más lento, así que recurre a él solo cuando una cadena literal no sirva.
¿Cómo actualizar plugins y el core en varios sitios?
Un único comando actualiza todo lo que tenga una actualización disponible, sin paginación del escritorio ni casillas por plugin:
wp plugin update --all
wp core update
wp core update-db
wp core update-db ejecuta la rutina de actualización de la base de datos de WordPress, que es el paso que el escritorio realiza por ti en la pantalla de actualización tras actualizar el core. Ejecútalo después de wp core update para que la actualización termine en lugar de quedarse a medias.
Combinado con los alias que se ven más abajo, la misma línea se convierte en wp @all plugin update --all y alcanza secuencialmente todas las instalaciones que mantienes.
Exportar antes, importar después
wp db export delega en mysqldump y toma el host, el nombre, el usuario y la contraseña de la base de datos desde wp-config.php, así que nunca escribes datos de conexión. Dale un nombre de archivo explícito; si lo omites, escribirá {dbname}-{Y-m-d}-{random-hash}.sql.
wp db export backup-$(date +%Y%m%d-%H%M%S).sql
Restaurar es la imagen especular:
wp db import backup-20250413-141055.sql
wp db import acepta tanto un nombre de archivo como entrada por tubería, de modo que puedes enviar una exportación directamente de un host a otro por ssh. Para una estrategia a más largo plazo que un simple volcado antes de un cambio arriesgado, los artículos de OpenReplay sobre copias de seguridad en WordPress cubren la programación y el almacenamiento externo.
¿Cómo volver a entrar en un sitio del que estás bloqueado?
Tres comandos cubren casi cualquier bloqueo, en el orden en que los ejecutarías bajo presión. Crear un administrador nuevo, restablecer la contraseña de un usuario existente o sacar por completo a los plugins de la ecuación:
wp user create ops ops@example.com --role=administrator
wp user reset-password admin --show-password --skip-email
wp plugin deactivate --all
wp user reset-password genera una nueva contraseña; --show-password la imprime en la terminal y --skip-email evita que la notificación llegue a un buzón que quizá no controles. wp plugin deactivate acepta --all para desactivarlo todo, además de --exclude=<name> para mantener activa una lista separada por comas.
Cuando lo que rompió el administrador es un error fatal en un plugin, WP-CLI puede fallar al arrancar por la misma razón que el sitio. El parámetro global --skip-plugins impide que se carguen todos los plugins, o una lista concreta, durante la ejecución del comando:
wp plugin deactivate broken-plugin --skip-plugins
Omitirlos no cambia el estado almacenado; un plugin omitido de esta forma sigue apareciendo como activo. Solo te da un arranque funcional para que la desactivación pueda ejecutarse. Tampoco ayuda cuando el código fatal está en un mu-plugin, porque WP-CLI carga los mu-plugins en cualquier caso. Este es el momento en que la mayoría de quienes mantienen sitios necesitan WP-CLI por primera vez, y es más rápido que abrir un cliente FTP y renombrar directorios de plugins. Una vez recuperado el administrador, la parte diagnóstica del trabajo está cubierta en el artículo de OpenReplay sobre la pantalla blanca de la muerte en WordPress.
Ejecutar PHP puntual con wp eval
wp eval ejecuta PHP arbitrario contra una instalación de WordPress completamente cargada. No hay equivalente en el escritorio, y ahí está la gracia: cualquier función que registre un plugin, cualquier opción, cualquier consulta, se convierte en una sola línea.
wp eval 'echo get_option( "siteurl" );'
wp eval 'echo count( get_users( [ "role" => "administrator" ] ) );'
Cualquier cosa más larga debe ir en un archivo. wp eval-file recibe la ruta a un archivo PHP, entrega al script los argumentos posicionales adicionales como $args y omitirá por completo el arranque de WordPress si pasas --skip-wordpress. Tu código se ejecuta dentro de un método, así que cada global que utilices necesita su propia línea global.
No existe modo de prueba para wp eval. Lo que el script escriba, queda escrito. Ese es el argumento más claro a favor de la exportación.
¿Cómo ejecutar WP-CLI contra un host remoto?
Aquí es donde la herramienta deja de ser una simple comodidad. El parámetro global --ssh de WP-CLI tiene la forma --ssh=[<scheme>:][<user>@]<host>[:<port>][<path>] y funciona entregando tu comando al binario ssh, que a su vez lo pasa al WP-CLI que está al otro extremo.
wp --ssh=dev_user@example.com:2222~/webapps/production plugin list
| Componente | Valor aquí | Valor por defecto si se omite |
|---|---|---|
| scheme | (omitido) | ssh |
| user | dev_user | tu usuario actual del sistema |
| host | example.com | obligatorio |
| port | 2222 | 22 |
| path | ~/webapps/production | el directorio home del usuario ssh |
La ruta no lleva separador. Escríbela justo después del puerto, o justo después del host si has omitido el puerto, y empiézala con / o ~. Además de ssh, la referencia de configuración del handbook documenta vagrant, docker, docker-compose y docker-compose-run. Este último arranca un contenedor nuevo con docker-compose run en lugar de usar uno que ya esté levantado.
Hay un requisito absoluto: el servidor remoto necesita su propio WP-CLI, y tiene que responder a wp. Un wp que funciona cuando inicias sesión manualmente puede seguir devolviendo command-not-found a través de --ssh, porque la shell que ejecuta un comando remoto no construye el mismo $PATH. La mayoría de distribuciones colocan cerca del comienzo de ~/.bashrc una comprobación que sale antes de tiempo cuando la shell no es interactiva, de modo que cualquier línea PATH situada más abajo nunca se ejecuta; zsh, en esa situación, lee ~/.zshenv en lugar de ~/.zshrc. La solución es definir $PATH explícitamente en el lado remoto.
Escribir esa cadena dos veces ya es suficiente. Registra alias en el wp-cli.yml de tu proyecto o en tu ~/.wp-cli/config.yml global:
@prod:
ssh: deploy@example.com~/webapps/production
@stage:
ssh: deploy@staging.example.com~/webapps/staging
@all:
- @prod
- @stage
wp @prod plugin update --all
wp @all core check-update
Un grupo de alias ejecuta una sola invocación contra varias instalaciones, que es la diferencia entre mantener diez sitios de clientes y entrar en diez escritorios. Para una instalación local que no esté en tu directorio actual, el parámetro global --path le indica a WP-CLI dónde están los archivos de WordPress:
wp --path=/var/www/example.com/htdocs plugin update --all
Qué hacer a continuación
La única idea que merece la pena llevarse de aquí: WP-CLI entiende las estructuras de datos de WordPress, y mysql y phpMyAdmin no, y por eso un cambio de dominio corresponde a wp search-replace y a nada más. Elige la próxima migración que tengas programada, escribe la línea con --dry-run, lee el informe y ejecuta wp db export antes de quitar el flag. Todo lo anterior es irreversible en el instante en que pulsas intro.
Preguntas frecuentes
¿wp search-replace actualiza todos los sitios de una red multisitio?
No. Funciona sobre las tablas que el propio WordPress registra, así que en multisitio obtienes solo las tablas del sitio actual, a menos que añadas --network. Para alcanzar todas las tablas de la base de datos, sea cual sea su prefijo y sepa o no WordPress de su existencia, usa --all-tables, que tiene prioridad sobre --network y --all-tables-with-prefix. En una red, añade también --url para que WP-CLI arranque en el sitio correcto.
¿Por qué WP-CLI se niega a ejecutarse como root?
WP-CLI se detiene con un error YIKES cuando detecta al usuario root. Todo lo que hay dentro de la instalación, incluidos plugins y temas que no has escrito tú, heredaría el alcance de root sobre el servidor, de modo que un solo fragmento de código hostil podría tomar la máquina entera. El flag --allow-root omite la comprobación y los contenedores que corren como root suelen necesitarlo, pero el proyecto desaconseja su uso. Ejecútalo en su lugar con el usuario del sistema propietario de los archivos de WordPress.
¿Qué significa el error 'This does not seem to be a WordPress installation'?
WP-CLI no encontró archivos del core de WordPress donde buscó, así que nunca arrancó. Ejecuta el comando desde el directorio que contiene wp-admin, wp-content y wp-includes, o apúntalo a la instalación con el parámetro global --path. Pasa el valor con el signo igual, --path=/var/www/html, porque un argumento separado por espacio deja el flag sin valor y el mismo error se repite.
¿WP-CLI funciona en Windows?
WP-CLI está pensado para un entorno tipo UNIX como Linux, macOS, FreeBSD o Cygwin, y solo cuenta con soporte parcial en Windows, así que WSL o Cygwin es la vía fiable en una máquina Windows. También necesita WordPress 4.9 o posterior, y cualquier versión anterior a la actual de WordPress puede no funcionar por completo.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k