¿Por qué este script falla cuando se ejecuta desde cron, pero funciona cuando se ejecuta manualmente?

¿Por qué este script falla cuando se ejecuta desde cron, pero funciona cuando se ejecuta manualmente?

Tengo un script bash relativamente simple que funciona muy bien cuando se invoca directamente, pero falla cuando se ejecuta mediante cron. ¿Por qué falla esto y cómo puedo hacer que funcione mediante cron?

#!/bin/bash
apt-get update -y
apt-get upgrade -y
apt-get install boinc-client -y

Una vez que cron haya intentado ejecutarlo, una invocación manual generará este error:

dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.

Pero siempre que se ejecute manualmente la primera vez, funciona bien.

Respuesta1

La respuesta habitual a este tipo de preguntas es que los trabajos cron se ejecutan en shells no interactivos y sin inicio de sesión, por lo que la mayoría de los archivos de inicio de su shell (tanto los de todo el sistema /etccomo los archivos de puntos personales en su directorio de inicio) no tienen origen ( leídos y ejecutados), porque la mayoría de los archivos de inicio de shell se aplican a shells de inicio de sesión (el primer shell que ve cuando inicia sesión en la computadora) o shells interactivos (shells que están conectados a terminales, sesiones ssh o emuladores de terminal porque un usuario es interactuando con ellos a través de dicho terminal).

Entonces, si coloca un comando en un trabajo cron que en realidad depende de alguna configuración del entorno (incluidos PATHlos cambios) que generalmente ocurre en lugares como /etc/profile, /etc/bashrc, ~/.profileo ~/.bashrc, esa configuración no se realizará para un trabajo cron. El formato de archivo cron le permite especificar variables de entorno para sus trabajos, por lo que es posible que desee especificarlo BASH_ENVo ENVapuntarlo a un script de inicio de shell en el origen. Consulte la sección "Invocación" de la bash(1)página de manual.

Respuesta2

Esto no califica como una respuesta, pero no puedo comentar. Sugerencias:

  1. anteponga lo siguiente a su script bash. La última línea registrada en la salida del correo será el comando fallido.

    set -x
    set -e
    
    • asegúrese de tener sendmail (instale un paquete proporcionado como postfixo esmtp)
    • instalar un lector de correo (recomendado mutt)
    • asegúrese de que el correo le llegue
      • vía postfix (el instalador puede hacerlo automáticamente): root: my-user-nameagregar /etc/aliaseso/etc/postfix/aliases
      • vía cron: agregar MAILTO="my-user-name"al crontabarchivo apropiado
  2. Verifique que el script se ejecute en un entorno diferente. Especifique la ruta completa a apt-get (probablemente no sea el culpable ya que se sabe que se encontró apt-get) y ejecútelo en una consola (no en una terminal) fuera de X. (algunos scripts de configuración de dpkg requieren una sesión X).

    • modifique el script para usar rutas absolutas, es decir /usr/bin/apt-get update -y(reemplace con la ruta correcta)
    • cambiar a una consola presionandoctrl-alt-f1
    • cambiar al usuario root:sudo -i
    • iniciar un shell sin inicio de sesión sin un entorno: env -i /bin/bash --noprofile --norc(reemplazar con la ruta correcta)
    • ejecute el script: /my/full/path/to/cronscript. ¿Funciona?
  3. ¿El guión tiene permiso? ¿Estás utilizando el sistema crontab? (una vez más, probablemente no sea el culpable)

    • Ha indicado que está utilizando el crontab del sistema, así que omita esto.
  4. ¿Apt-get requiere soporte de sesión (consolekit o systemd)? Sin embargo, esto es sólo un tiro en la oscuridad.

    • No sé lo suficiente para ser de ayuda.

Respuesta3

Logré resolverlo sin apenas entender lo que estaba pasando. Resultó que, aunque estaba ejecutando desde el crontab raíz, los comandos apt-get todavía necesitaban un sudo delante de ellos. Lógicamente esperaba que no fuera necesario ya que el script ya se estaba ejecutando "como root", pero una vez que agregué sudo... todo funcionó exactamente como se esperaba.

información relacionada