¿Dónde se establece la ruta del cron?

34

Cron no usa la ruta del usuario cuyo crontab es y, en cambio, tiene la suya. Se puede cambiar fácilmente agregando PATH=/foo/baral principio del crontab, y la solución clásica es usar siempre rutas absolutas a los comandos ejecutados por cron, pero ¿dónde se define la RUTA predeterminada de cron?

Creé un crontab con los siguientes contenidos en mi sistema Arch (cronie 1.5.1-1) y también probé en un cuadro Ubuntu 16.04.3 LTS con los mismos resultados:

$ crontab -l
* * * * * echo "$PATH" > /home/terdon/fff

Eso impreso:

$ cat fff
/usr/bin:/bin

¿Pero por qué? La ruta predeterminada del sistema está configurada /etc/profile, pero eso incluye otros directorios:

$ grep PATH= /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"

No hay nada más relevante en /etc/environmento /etc/profile.d, los otros archivos que pensé podrían ser leídos por cron:

$ grep PATH= /etc/profile.d/* /etc/environment
/etc/profile.d/jre.sh:export PATH=${PATH}:/usr/lib/jvm/default/bin
/etc/profile.d/mozilla-common.sh:export MOZ_PLUGIN_PATH="/usr/lib/mozilla/plugins"
/etc/profile.d/perlbin.sh:[ -d /usr/bin/site_perl ] && PATH=$PATH:/usr/bin/site_perl
/etc/profile.d/perlbin.sh:[ -d /usr/lib/perl5/site_perl/bin ] && PATH=$PATH:/usr/lib/perl5/site_perl/bin
/etc/profile.d/perlbin.sh:[ -d /usr/bin/vendor_perl ] && PATH=$PATH:/usr/bin/vendor_perl
/etc/profile.d/perlbin.sh:[ -d /usr/lib/perl5/vendor_perl/bin ] && PATH=$PATH:/usr/lib/perl5/vendor_perl/bin
/etc/profile.d/perlbin.sh:[ -d /usr/bin/core_perl ] && PATH=$PATH:/usr/bin/core_perl

Tampoco hay nada relevante en ninguno de los archivos /etc/skel, como era de esperar, ni se está configurando en ningún /etc/cron*archivo:

$ grep PATH /etc/cron* /etc/cron*/*
grep: /etc/cron.d: Is a directory
grep: /etc/cron.daily: Is a directory
grep: /etc/cron.hourly: Is a directory
grep: /etc/cron.monthly: Is a directory
grep: /etc/cron.weekly: Is a directory
/etc/cron.d/0hourly:PATH=/sbin:/bin:/usr/sbin:/usr/bin

Entonces, ¿dónde se establece la RUTA predeterminada de cron para las crontabs de usuario? ¿Está codificado en cronsí mismo? ¿No lee algún tipo de archivo de configuración para esto?

terdon
fuente
3
No hay ninguna razón para cronmirar /etc/profileo preocuparse por un shell en particular. Una mejor pregunta es ¿por qué no cronleer PATHdesde login.defs(en Linux) o login.conf(en * BSD). Supongo que en última instancia es un detalle de implementación.
Satō Katsura el
@ SatōKatsura seguro, solo lo mencioné /etc/profileporque usa la misma sintaxis ( var=value) que en cronsí misma, por lo que sería bastante fácil de hacer y /etc/profile, que yo sepa, está muy extendido. Lo que me sorprendió es que no pude encontrarlo en ningún lugar, por lo que parecía que estaba codificado. Como es el caso, como Stephen explicó a continuación.
terdon
A las personas que usan zshcomo su shell interactivo no les importa /etc/profile(lo cual es específico para bash)
Basile Starynkevitch
2
@BasileStarynkevitch no, no es específico para bash en absoluto ! ¡Todo lo contrario! Si bien hay algunos shells que no lo leen (la familia c-shell AFAIK), zsh no es uno de ellos. Vea la página de manual de zsh, si no me cree. En cualquier caso, los shells interactivos son irrelevantes, ya que los diversos profilearchivos solo se leen por shells de inicio de sesión. Estos pueden o no ser interactivos.
terdon
1
A veces, ejecutar stringscontra un programa también puede ayudar a encontrar estos valores codificados.
jrw32982 es compatible con Monica el

Respuestas:

47

Está codificado en el código fuente (ese enlace apunta al Debian actual cron; dada la variedad de cronimplementaciones, es difícil elegir uno, pero es probable que otras implementaciones sean similares):

#ifndef _PATH_DEFPATH
# define _PATH_DEFPATH "/usr/bin:/bin"
#endif

#ifndef _PATH_DEFPATH_ROOT
# define _PATH_DEFPATH_ROOT "/usr/sbin:/usr/bin:/sbin:/bin"
#endif

cronno lee las rutas predeterminadas de un archivo de configuración; Me imagino que el razonamiento es que admite la especificación de rutas que ya se utilizan PATH=en cualquier trabajo temporal, por lo que no es necesario poder especificar un valor predeterminado en otro lugar. (El valor predeterminado codificado se usa si nada más especifica una ruta en una entrada de trabajo ).

Stephen Kitt
fuente
Tenga en cuenta que, a pesar de la existencia de la _PATH_DEFPATH_ROOTdefinición, confirme (usando un trabajo cron de echo $PATH > /testfile) después de editar el crontab de root usando crontab -eDebian Stretch que el crontab de root también usa _PATH_DEFPATH, es decir, "/ usr / bin: / bin", no _PATH_DEFPATH_ROOT . Esto también se confirma mediante el segundo enlace del código fuente en esta respuesta (en la que _PATH_DEFPATH_ROOTno se usa). No me queda claro si esta definición huérfana es un error.
njahnke
8

Agregando a la respuesta de Stephen Kitt, hay un archivo de configuración que establece PATHpara cron en Ubuntu, e cron ignora eso PATHpara usar el valor predeterminado codificado (o PATHs establecido en los propios crontabs). El archivo es /etc/environment. cronConfiguración de PAM de la nota :

$ cat /etc/pam.d/cron
...   
# Read environment variables from pam_env's default files, /etc/environment
# and /etc/security/pam_env.conf.
session       required   pam_env.so

# In addition, read system locale information
session       required   pam_env.so envfile=/etc/default/locale
...

Esto es fácilmente verificable. Agregue una variable para /etc/environment, por ejemplo foo=bar, ejecutar env > /tmp/foocomo cronjob y ver como se foo=barmuestra en la salida.


¿Pero por qué? La ruta predeterminada del sistema se establece en / etc / profile, pero eso incluye otros directorios:

$ grep PATH= /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"

Eso es cierto en Arch Linux, pero en Ubuntu, la base PATHestá establecida /etc/environment. Archivos en /etc/profile.dtachuela a un existente PATH, y puede agregarlo a él ~/.pam_environment. Tengo un error archivado sobre el comportamiento de Arch .

Lamentablemente, /etc/pam.d/cronno incluye la lectura de ~/.pam_environment. Extrañamente, /etc/pam.d/atd hace incluir ese archivo:

$ cat /etc/pam.d/atd
#
# The PAM configuration file for the at daemon
#

@include common-auth
@include common-account
session    required   pam_loginuid.so
@include common-session-noninteractive
session    required   pam_limits.so
session    required   pam_env.so user_readenv=1

... pero los comandos ejecutados ataparentemente heredan el entorno disponible al crear el attrabajo (por ejemplo, env -i /usr/bin/at ...parece ejecutar trabajos con un entorno muy limpio).

Enmendar /etc/pam.d/crontener user_readenv=1parece no causar problemas, y las variables ~/.pam_environmentcomenzaron a aparecer bien (excepto PATH, por supuesto).


En total, establecer variables de entorno para cron parece ser un negocio desordenado. El mejor lugar parece estar en la especificación del trabajo en sí, aunque solo sea porque no sabe qué variables de entorno heredadas cron podría decidir ignorar (sin leer la fuente).

muru
fuente
Con respecto a los attrabajos, si volca un attrabajo, verá que configura explícitamente el entorno para que coincida con el entorno cuando se creó el trabajo.
Stephen Kitt el