> ## Documentation Index
> Fetch the complete documentation index at: https://ayakaleaf-pro.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Actualizar automáticamente las imágenes TeX Live Full

> Usa cron para actualizar las imágenes Docker de TeX Live que usa el compilador en sandbox compatible con Overleaf.

Por lo general, cada vez que ejecutas `bin/up`, [using-the-toolkit](/es/on-premises/installation/using-the-toolkit "mention") actualizará automáticamente nuestra imagen TeX Live Full. Para evitar actualizaciones manuales, puedes automatizar las actualizaciones de tu imagen de sandbox de TeX Live con el siguiente script. Añádelo como tarea cron, asegurándote de que el usuario de cron tenga permiso para ejecutar `docker`. Ejecuta `crontab -e` para añadir la siguiente línea al final.

```cron title="crontab -e" theme={null}
0 * * * * /usr/bin/flock -n /tmp/pull-texlive.lock /usr/local/bin/pull-texlive.sh
```

`flock -n` omite una ejecución mientras la anterior siga teniendo el bloqueo, de modo que una descarga lenta nunca se acumula.

<Tabs>
  <Tab title="Conexión directa">
    ```bash title="/usr/local/bin/pull-texlive.sh" theme={null}
    #!/usr/bin/env bash
    set -uo pipefail

    IMAGE="ghcr.io/ayaka-notes/texlive-full"
    TAGS=(2020.1 2021.1 2022.1 2023.1 2024.1 2025.1 2026.1)
    LOG=/var/log/pull-texlive.log

    exec >>"$LOG" 2>&1

    # Hours since the epoch, modulo the tag count: one tag per hour,
    # so all 7 tags are refreshed every 7 hours.
    idx=$(( $(date +%s) / 3600 % ${#TAGS[@]} ))
    tag="${TAGS[$idx]}"

    echo "===== $(date -Is) pulling $tag (idx=$idx) ====="

    if timeout 50m docker pull "$IMAGE:$tag"; then
      echo "OK   $tag"
    else
      echo "FAIL $tag (exit $?)"
    fi

    docker image prune -f
    docker system df | tail -n +2
    ```
  </Tab>

  <Tab title="Usar un sitio espejo">
    ```bash title="/usr/local/bin/pull-texlive.sh" theme={null}
    #!/usr/bin/env bash
    set -uo pipefail

    MIRROR="ghcr.nju.edu.cn"
    CANONICAL="ghcr.io"
    REPO="ayaka-notes/texlive-full"
    TAGS=(2020.1 2021.1 2022.1 2023.1 2024.1 2025.1 2026.1)
    LOG=/var/log/pull-texlive.log

    exec >>"$LOG" 2>&1

    # Hours since the epoch, modulo the tag count: one tag per hour,
    # so all 7 tags are refreshed every 7 hours.
    idx=$(( $(date +%s) / 3600 % ${#TAGS[@]} ))
    tag="${TAGS[$idx]}"

    echo "===== $(date -Is) pulling $tag (idx=$idx) via $MIRROR ====="

    if timeout 50m docker pull "$MIRROR/$REPO:$tag"; then
      # Retag to the canonical name the compiler is configured with. This only
      # adds a second name for the same layers; nothing is copied.
      docker tag "$MIRROR/$REPO:$tag" "$CANONICAL/$REPO:$tag"
      echo "OK   $tag"
    else
      echo "FAIL $tag (exit $?)"
    fi

    docker image prune -f
    docker system df | tail -n +2
    ```
  </Tab>
</Tabs>

**Por qué una rotación horaria en lugar de descargarlo todo de una vez**: la etiqueta se deriva del reloj (horas desde epoch, módulo el número de etiquetas), por lo que la tarea no tiene estado: nada registra "dónde lo dejamos", y el ciclo se vuelve a alinear por sí solo tras un reinicio o una hora perdida. Cada ejecución afecta a una sola etiqueta; cuando el digest del registro no ha cambiado, la descarga es solo una comprobación del manifiesto (`Image is up to date`) y termina en segundos. Una actualización real descarga como máximo una imagen por hora, limitada por `timeout 50m`, y `docker image prune -f` elimina las capas que quedan huérfanas al moverse la etiqueta.

Para comprobar que la sincronización funciona correctamente:

```bash theme={null}
tail -20 /var/log/pull-texlive.log     # each run ends with "OK <tag>" or "FAIL <tag>"
grep -c '^FAIL' /var/log/pull-texlive.log
```

Cuando se publique una nueva versión de TeX Live, añade su etiqueta al array `TAGS`; la longitud de la rotación se adapta automáticamente. Las horas en las que el host está apagado se omiten, no se ponen en cola; las etiquetas afectadas simplemente se actualizan en su siguiente turno.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.