bash - tiempo - debian cron
¿Cómo simular el entorno cron ejecuta un script con? (12)
Normalmente tengo varios problemas con la forma en que cron ejecuta las secuencias de comandos, ya que normalmente no tienen la configuración de mi entorno. ¿Hay alguna forma de invocar bash (?) De la misma manera que lo hace cron para que pueda probar los scripts antes de instalarlos?
Agrega esto a tu cron:
30 08 * * * env > ~/cronenv
Después de que se ejecuta, haga esto:
env - `cat ~/cronenv` /bin/sh
Esto supone que su cron ejecuta / bin / sh, que es el valor predeterminado independientemente del shell predeterminado del usuario.
Cree un trabajo cron que ejecute env y redirija stdout a un archivo. Use el archivo junto con "env -" para crear el mismo entorno que un trabajo cron.
Cron proporciona solo este entorno por defecto:
- Directorio de inicio del usuario
HOME
-
LOGNAME
login del usuario -
PATH=/usr/bin:/usr/sbin
-
SHELL=/usr/bin/sh
Si necesita más puede obtener una secuencia de comandos donde defina su entorno antes de la tabla de programación en el crontab.
De forma predeterminada, cron
ejecuta sus trabajos utilizando la idea de sh
de su sistema. Este podría ser el shell o el dash
Bourne, ash
, ksh
o bash
(u otro) con un enlace simbólico a sh
(y, como resultado, se ejecuta en modo POSIX).
Lo mejor que puede hacer es asegurarse de que sus scripts tengan lo que necesitan y de asumir que no se les proporciona nada. Por lo tanto, debe usar especificaciones de directorio completas y establecer variables de entorno como $PATH
usted mismo.
Dependiendo del shell de la cuenta
sudo su
env -i /bin/sh
o
sudo su
env -i /bin/bash --noprofile --norc
De http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html
La respuesta https://.com/a/2546509/5593430 muestra cómo obtener el entorno cron y usarlo para su script. Pero tenga en cuenta que el entorno puede diferir según el archivo crontab que utilice. Creé tres entradas cron diferentes para guardar el entorno a través de env > log
. Estos son los resultados en un Amazon Linux 4.4.35-33.55.amzn1.x86_64.
1. Global / etc / crontab con usuario root
MAILTO=root
SHELL=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
PWD=/
LANG=en_US.UTF-8
SHLVL=1
HOME=/
LOGNAME=root
_=/bin/env
2. Usuario crontab de root ( crontab -e
)
SHELL=/bin/sh
USER=root
PATH=/usr/bin:/bin
PWD=/root
LANG=en_US.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/env
3. Script en /etc/cron.hourly/
MAILTO=root
SHELL=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
_=/bin/env
PWD=/
LANG=en_US.UTF-8
SHLVL=3
HOME=/
LOGNAME=root
Lo más importante es que PATH
, PWD
y HOME
difieren. Asegúrese de configurar estos en sus scripts cron para confiar en un entorno estable.
No creo que haya; La única forma que conozco de probar un trabajo cron es configurarlo para que se ejecute un minuto o dos en el futuro y luego esperar.
No olvide que dado que el padre de Cron es init, ejecuta programas sin un terminal de control. Puedes simular eso con una herramienta como esta:
Otra forma sencilla que he encontrado (pero puede ser propensa a errores, todavía estoy probando) es obtener los archivos de perfil de su usuario antes de su comando.
Editando un script /etc/cron.d/:
* * * * * user1 comand-that-needs-env-vars
Se convertiría en:
* * * * * user1 source ~/.bash_profile; source ~/.bashrc; comand-that-needs-env-vars
Sucio, pero hizo el trabajo por mí. ¿Hay una manera de simular un inicio de sesión? Sólo un comando que podría ejecutar? bash --login
no funcionó. Parece que esa sería la mejor manera de hacerlo.
EDIT: Esto parece ser una solución sólida: http://www.epicserve.com/blog/2012/feb/7/my-notes-cron-directory-etccrond-ubuntu-1110/
* * * * * root su --session-command="comand-that-needs-env-vars" user1 -l
Respondiendo seis años después: el problema de la falta de coincidencia en el entorno es uno de los problemas resueltos por los "temporizadores" de systemd
como reemplazo de cron. Ya sea que ejecute el "servicio" de systemd desde la CLI o mediante cron, recibirá exactamente el mismo entorno, evitando el problema de desajuste del entorno.
El problema más común para hacer que los trabajos cron fallen cuando se pasan manualmente es el $PATH
predeterminado restrictivo establecido por cron, que es este en Ubuntu 16.04:
"/usr/bin:/bin"
Por el contrario, el valor predeterminado de $PATH
establecido por systemd
en Ubuntu 16.04 es:
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Así que ya hay más posibilidades de que un temporizador de sistema encuentre un binario sin mayores problemas.
La desventaja de los temporizadores systemd es que hay un poco más de tiempo para configurarlos. Primero crea un archivo de "servicio" para definir lo que desea ejecutar y un archivo de "temporizador" para definir el programa para ejecutarlo y finalmente "habilitar" el temporizador para activarlo.
Tu puedes correr:
env - your_command arguments
Esto ejecutará your_command con el entorno vacío.
Un par de enfoques:
Exportar cron env y su origen:
Añadir
* * * * * env > ~/cronenv
a su crontab, déjelo correr una vez, apáguelo y luego corra
env - `cat ~/cronenv` /bin/sh
Y ahora estás dentro de una sesión de
sh
que tiene el entorno de Cron.Trae tu entorno a cron
Podrías saltarte el ejercicio y simplemente hacer una
. ~/.profile
. ~/.profile
delante de su trabajo cron, por ejemplo* * * * * . ~/.profile; your_command
Usar pantalla
Las dos soluciones anteriores aún fallan porque proporcionan un entorno conectado a una sesión X en ejecución, con acceso a
dbus
etc. Por ejemplo, en Ubuntu,nmcli
(Network Manager) funcionará en los dos enfoques anteriores, pero aún fallará en cron.* * * * * /usr/bin/screen -dm
Agregue la línea anterior a cron, deje que se ejecute una vez, apáguelo. Conéctate a tu sesión de pantalla (pantalla -r). Si está verificando que se ha creado la sesión de pantalla (con
ps
), tenga en cuenta que a veces están en mayúsculas (por ejemplo,ps | grep SCREEN
)Ahora incluso
nmcli
y similares fallarán.