El proyecto wpdirectory.net es fantástico, es un proyecto de Peter Booker para buscar mediante expresiones regulares cadenas en el código y el texto de todos los archivos de los repositorios de plugins y temas de WordPress.
Este proyecto es una herramienta esencial para el equipo de plugins, nos permite buscar copias de plugins, posibles violaciones de las normas del repositorio, problemas de seguridad, y analizar el código de todo el repositorio para mejorar nuestras herramientas internas.
Hace tiempo me planteé que, por resiliencia, el equipo de plugins necesita tener su propia versión de esta herramienta.
Las alternativas
Tal como viene indicado en el handbook, hay herramientas para descargar el repositorio. También hay herramientas como WPDS para además buscar en él.
Desgraciadamente, a día de hoy, esto es poco funcional porque el repositorio es enorme y, aunque se use ag
para buscar (que es extremadamente rápido), una búsqueda tarda del orden de 4 minutos.
Esta no era una alternativa, de modo que intenté hacer uso directamente del proyecto wpdir, que está abierto en Github y que, desgraciadamente, no llegué a hacer funcionar en mi entorno, pero si que pude ver cómo funciona.
wpdir usa:
- wpds para descargar y actualizar el repositorio.
- hound , que a su vez usa codesearch, para indexar el código y permitir hacer búsquedas rápidas mediante expresiones regulares.
Gracias a todas las personas que han contribuido con estos proyectos de código abierto tenemos estas herramientas disponibles y puedo seguir avanzando en este artículo.
Nuestro propio buscador
Preparando el entorno
Necesitamos un servidor que sea lo suficientemente potente, con suficiente almacenamiento y memoria. Para este caso he usado un servidor con 8 cores compartidos AMD EPYC™ 7002, 16Gb de RAM y 240Gb de almacenamiento SSD NvME.
El servidor corre sobre Ubuntu y tiene los siguientes paquetes adicionales instalados:
sudo apt install subversion make npm golang-go silversearcher-ag
Además, hay que hacer algunos ajustes adicionales al sistema operativo, dado que va a trabajar con un número enorme de archivos y va a hacer un uso de recursos fuera de lo habitual.
Para esto, dado que no soy sysadmin, simplemente he puesto valores grandes, no sé realmente qué estoy haciendo ni qué implicaciones tiene, si eres un sysadmin puedes ayudarme a establecer mejor estos valores.
Añadir estas líneas a /etc/sysctl.conf
fs.inotify.max_user_instances = 1024
vm.max_map_count = 262144
Edita estos dos archivos:/etc/systemd/system.conf
/etc/systemd/user.conf
En ambos casos busca la propiedad DefaultLimitNOFILE
, descomenta y déjala así:
DefaultLimitNOFILE=262144:5242880
Tendrás que reiniciar después de aplicar estos cambios, y comprobar con ulimit -n
que se han aplicado.
Descargar los plugins
Lo primero que necesitamos es wpds, que descarga todo el repositorio actual de WordPress y permite sincronizar los cambios más recientes.
Para ello simplemente hay que ejecutar ./wpds update plugins
que creará una carpeta ./plugins/
dónde se introducirá cada plugin en una carpeta nueva.
Actualmente descargará más de 60.000 plugins que ocuparán unos 95Gb de espacio. El proceso tarda alrededor de 4 horas.
Configurar el buscador
La instalación es tan simple como indican
git clone https://github.com/hound-search/hound.git
cd hound
make
La configuración se hace a través de un fichero JSON en el que se puede indicar de qué repositorios leerá la información. He creado un JSON de este tipo.
{
"max-concurrent-indexers":2,
"max-connections":50,
"dbpath":"db",
"title":"Plugins search",
"health-check-uri":"/healthz",
"repos":{
"woocommerce":{
"url":"file:///mnt/plugins/plugins/woocommerce",
"url-pattern": {
"base-url":"https://plugins.trac.wordpress.org/browser/woocommerce/trunk/{path}{anchor}",
"anchor":"#L{line}"
},
"vcs":"local"
}
}
}
Que carga localmente desde /mnt/plugins/plugins/woocommerce
un plugin llamado woocommerce
cuyo enlace al código es https://plugins.trac.wordpress.org/browser/woocommerce/trunk/{path}{anchor}
.
Se este modo indexará de forma independiente el código de este plugin y luego nos saldrá de forma agrupada, además haciendo esto evitamos el límite técnico de 4Gb para los index que tiene codesearch.
Esto hay que hacerlo para los más de 60.000 plugins que hay.
Venga, comienza a escribir el JSON.
Uno a uno.
Estoy esperando.
Bueno, vale, en verdad hay una alternativa, pero es un script en PHP, no soy perfecto.
<?php
$dir = "/mnt/plugins/plugins"; // Plugins dir
$items = scandir($dir);
var_dump('Number of repositories: '.sizeof($items));
$hound_config = array(
"max-concurrent-indexers" => 2,
"dbpath" => "/mnt/plugins/db",
"title" => "Plugins Search",
"health-check-uri" => "/healthz",
"repos" => []
);
foreach($items as $item) {
// Allows us creating the indexing in batches.
$limit = 1000000;
if(sizeof($hound_config["repos"])>$limit){
var_dump('Repositories limited to: '.$limit);
break;
}
if(is_dir($dir . DIRECTORY_SEPARATOR . $item) && $item != "." && $item != "..") {
$hound_config["repos"][$item] = [
"url" => "file://".$dir."/".$item,
"url-pattern" => [
"base-url" => "https://plugins.trac.wordpress.org/browser/".$item."/trunk/{path}{anchor}",
"anchor" => "#L{line}"
],
"vcs" => "local"
];
}
}
$json = json_encode($hound_config, JSON_UNESCAPED_SLASHES);
file_put_contents("config.json", $json);
Esto creará este fichero config.json para todos los repositorios almacenados en /mnt/plugins/plugins
. Tiene una pequeña condición para limitar el número de repositorios creados, útil para probar las primeras ejecuciones.
Ejecutar el buscador
Una vez creado el archivo de configuración hay que lanzar hound, con el siguiente comando.
./.build/bin/houndd
Comenzará a indexar el contenido de todos estos repositorios uno por uno y a copiar los contenidos en texto a su directorio. Esto ocupa aproximadamente 33Gb y el proceso tarda alrededor de 5 horas.
Una vez terminado, levantará un servidor web en el puerto 6080 desde el cual podemos realizar nuestras búsquedas.
Mantenerlo en ejecución
Para que se mantenga en ejecución, se vuelva a levantar cuando falla (cosa que ocurre en esta configuración, dado que llega al límite de memoria en búsquedas muy genéricas) y se actualice, hay que hacer varias operaciones adicionales.
Servicio de sistema
Crea el servicio de sistema hound, creando su archivo de servicio nano /etc/systemd/system/hound.service
[Unit]
Description=Hound Daemon
After=network.target
StartLimitIntervalSec=30
[Service]
Type=simple
Restart=on-failure
RestartSec=5
User=hound
ExecStart=/mnt/plugins/hound/.build/bin/houndd -conf /mnt/plugins/config.json
[Install]
WantedBy=multi-user.target
Y actívalo con el comando systemctl enable hound
. Si el proceso falla (lo cual es probable que ocurra, se reiniciará automáticamente en unos 5 segundos).
¿Va todo bien? Puedes comprobarlo con systemctl status hound
Actualización
Con todo esto, actualizar ya es algo más sencillo con un pequeño script en BASH.
#!/bin/bash
cd /mnt/plugins
./wpds update plugins
php wpds-to-hound-config.php
systemctl restart hound
Que podemos ejecutar mediante cron, tal vez una vez al día.
crontab -e
0 9 * * * /mnt/plugins/update.sh
Deja una respuesta