El asterisco - cómo un asterisco en Cron puede quemarte un servidor sin que te enteres

Hacía unos meses que había migrado un script de un servidor a otro, lo había actualizado y programado el Cron, el programa que ejecuta a cada cierto tiempo una acción. Parecía todo andar bien pero luego de un tiempo noté algo: el consumo de CPU era elevado.

Era un buen VPS como para preocuparme pero noté que los sitios que alojaba tampoco tenían un tráfico bestial, sí eran grandes (mucho contenido en base de datos) pero no lograba entender qué estaba sucediendo. Esta es una de esas historias de un error estúpido pero que puede quitarte una enorme cantidad de tiempo tratando de descularlo. Equivocarse, resolver, aprender, sí, todo muy bonito pero ¿Quién no se mandó una de estas?

Llegué a probar de todo, desactivar plugins, actualizar PHP hasta la versión 8.0 (que, a todo esto, performó mejor), borrar contenido de las bases de datos, todo parecía mejorar un poco pero a día sobraban momentos en los que el procesador se iba al 100%.

Probé reiniciando servicios, pero lo mismo, al rato se volvía un desastre. Cambié el sistema de cacheo de los sitios, agregué Redis, llegué a cachear TODO para que servir una página fuese tan sólo tomar algo que ya estaba pre-procesado, metí Cloudflare, ¿qué más podía hacer?

Hasta que se me ocurrió actualizar el script que corría el Cron. El anterior estaba tan viejo que solía cortar la ejecución por usar una API vieja, pasé todo a lo último, lo nuevo.

Obviamente al ser un mejor script corría todas las veces que era llamado pero noté algo: parecía estar corriendo todo el tiempo sin parar, WTF?

Aquí cambié el foco y miré al cron, si se estaba ejecutando demasiado ¿Quién era el culpable? ¿Cron se volvió loco? A ver...

grep CRON /var/log/syslog

De pronto, para mi sorpresa, el script se estaba ejecutando a cada minuto del fucking día. CADA MINUTO, algo que debía ejecutarse una vez cada cuatro horas lo estaba haciendo TODO EL MALDITO TIEMPO. Esto debe haber estado así desde hace seis meses más o menos, me estaba violando el servidor sin asco.

Pero ¿Qué había configurado mal? Obvio que la culpa es siempre del usuario, en este caso yo, y fue tan estúpido como obvio. Un asterisco en vez de cero. Miré la config en el panel de control de VestaCP y vi esto...

Min Hour Day Month Day of week
* */2 * * *

El asterisco implica "ejecutar siempre", el cero "en el minuto cero", por alguna razón cuando cargué el cron puse asteriscos pensando que significaba "en cualquier minuto" porque mi cabeza estaba ubicada solamente en el campo de la hora.

El cron interpretó que le estaba pidiendo que ejecutara TODOS los minutos el mismo script, claro, asterisco es todos, venga, te lo disparo todos los minutos, a cada maldito minuto sale, total, ¿No es lo que me estás pidiendo?

Y así señores encontré que un puto asterisco estaba violentando mi servidor y durante todo este tiempo aprendí miles de trucos para hacer un sitio más eficiente, escribí código, aprendí de redis, de caché, de todo... al pedo :D Pero bueno, ese es el lado positivo! ja!

Un maldito simple y básico error de esos que pasás tan rápido que no te das cuenta. El servidor, un VPS en Digital Ocean, se la estaba bancando bastante bien porque no se quejaba demasiado, tan sólo tenía este recurente script ejecutándose una y otra vez pero el servidor resistía y muy de vez en cuando el CPU se estancaba en el 100%, pero siempre volvía.

No, no era MySQL por su cuenta, tampoco Apache, pero esos servicios se atoraban por culpa de este otro script que estaba ahí en el medio molestando.

Y vos, ¿cual de estas estupideces te mandaste alguna vez?

Otros posts que podrían llegar a gustarte...

Comentarios

  • Matias    

    Yo por cosas como esta me acostumbre a verificar todos los cron que armo en https://crontab.guru/ aunque ya los haya armado mil veces. 15s para verificarlo te pueden ahorrar muchos quilombos. También les agrego pid files si son algo que puede llegar a tardar en correr, eso me salvo el culo varias veces.

    • Responder
    • Citar
    • Comentado:
    • Muy buen artículo. Y trucos muy útiles, Matías. Gracias.

      • Responder
      • Citar
      • Comentado:
  • Coolturak    

    ¿Antes de hacer todo eso no se te ocurrió mirar con TOP el proceso que te estaba molestando? Estimo que lo hiciste y no te diste cuenta porque figuraba el proceso de php o apache y no lo relacionaste con el cron.

    • Responder
    • Citar
    • Comentado:
    • exacto, si hubiese sido un proceso separado (no un cron con php) hubiese sido más fácil pero al ser otro PHP no se separaba del apache normal. Era otro subproceso de Apache más

      • Responder
      • Citar
      • Comentado:
  • jorge    

    Una vez me olvide una pavadita, la clausa ON de un inner join... o sea basicamente le mande un producto cartesiano, que de dos tablas maso grandes el paaabre mysql sobre win2k se mando a fondo.
    El win2k decia "buehhhh tengo que reiniciar, crear un archivo de intercambio mas grande y re-arrancar el servicio"... y asi varias veces hasta que se quedo sin espacio de disco.
    En fin...

    • Responder
    • Citar
    • Comentado:
    • jaja quién no se mandó un DELETE sin el WHERE? , vamos!

      • Responder
      • Citar
      • Comentado:
      • Lelale    

        https://www.youtube.com/watch?v=i_cVJgIz_Cs

        ¿Como se pone el tag de videos e imágenes?

        • Citar
        • Comentado:
      • Gabriel    

        Si señor! yo vengo sosteniendo que el DELETE sin WHERE debería dar error de sintaxis

        • Citar
        • Comentado:
  • Lelale    

    " me estaba violando el servidor sin asco " ¡y por el asterisco!

    • Responder
    • Citar
    • Comentado:
  • nan    

    es increíble que todavía luchemos con el CRON, la interfaz es una patada; cargaste algo y no tenés forma de saber como se va a instanciar la regla efectivamente, por no hablar de los problemas de permisos que te pueden surgir.

    para monitorear los servidores a mi y a mi socio en su momento nos resultó muy práctico el servicio de uptimerobot.com, podes ponerle reglas. Antes de eso tenía unos scripts caseros que usaba para monitorear cosas raras, una de ellas era TOPs elevados

    Respecto a macanas: creo que la peor que me mandé fue meter un script en un servidor productivo que tenía citrix con unas cuantas VMs para que generara snapshots periodicamente (con la ingenua y benevolente intención de estar más tranquilo), y no recuerdo bien que pasó luego, creo que se comió todo el espacio libre que tenía el server y no nos dejaba liberarlo, nos generó una estructura en LVM que no la entendía ni montoto. Encima cuando leí técnicamente como funcionaban los snapshots de citrix, OMG no volví a dormir bien hasta que migramos el server a otra versión (y por suerte sin citrix)

    • Responder
    • Citar
    • Comentado:
  • Un par de anécdotas que costaron MUCHO dinero a la empresa.

    no las hice yo, pero una tuve que resolverla.

    contexto: sitio web con MILES de usuarios por minuto, de seguro lo usan.

    alguien definió una promoción para los clientes que vivieran en cierta ciudad por un fin de semana o asi.

    la info ya venia en el paquete de datos de cuando el usuario se logueaba.
    pero no tuvieron mejor idea que volver a ejecutar el pedido de datos (que tenia un costo por transaccion) para preguntar el CP.
    si el CP era el de la promo prendia una bandera para que el front mostrara un popup con una imagen (o algo asi)

    termino la promo, se comento el if y a otra cosa.

    tema, la transaccion que pedia los datos seguia activa, nos enteramos cuando a los 3 meses llega la "factura" interna por el costo operativo de consumir ese servicio. de pronto se habia duplicado sin haber duplicado el trafico.

    al ver el codigo nos dimos cuenta y se comento esa p!7# linea de codigo.

    costo: 150k verdes



    otra de hace un par de años, un cliente que consume nuestros servicios por webservice de pronto nos empieza a hacer peticiones cual ataque DDS.
    (cliente con mucho mas trafico que nosotros)

    la arquitectura empieza a escalar automaticamente, pero se encienden las luces rojas por todos lados (virtuales todas)

    resumen: el cliente pago FORTUNAS en uso del WS porque en vez de invocarlo una sola vez cuando el cliente se logueaba, lo hacian dentro del loop de su app web y se invocaba cada 15 segundos y encima se negaban a hacer un roll back y estuvieron 3 o 4 dias asi.

    no se bien cuanto terminaron pagando, pero mas de 6 ceros en color verde

    • Responder
    • Citar
    • Comentado:
    • Revisado: 14/05/2021 - 12:48:25
    • lo peor de esos casos es que no reaccionaran y prefirieran seguir unos días más así acumulando costo

      • Responder
      • Citar
      • Comentado:

Deje su comentario:

Tranquilo, su email nunca será revelado.
La gente de bien tiene URL, no se olvide del http/https
Para evitar bots, si se tardó mucho en leer la nota seguramente no sirva y tenga que intentar dos veces

Negrita Cursiva Imagen Enlace


comentarios ofensivos o que no hagan al enriquecimiento del post serán borrados/editados por el administrador