Onde está o PATH do cron definido?

34

O Cron não usa o caminho do usuário cujo crontab é e, em vez disso, possui o seu. Ele pode ser facilmente alterado adicionando-se PATH=/foo/barno início do crontab, e a solução alternativa clássica é sempre usar caminhos absolutos para os comandos executados pelo cron, mas onde é definido o PATH padrão do cron?

Criei um crontab com o seguinte conteúdo no meu sistema Arch (cronie 1.5.1-1) e também testei em uma caixa Ubuntu 16.04.3 LTS com os mesmos resultados:

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

Que imprimiu:

$ cat fff
/usr/bin:/bin

Mas por que? O caminho padrão do sistema está definido /etc/profile, mas isso inclui outros diretórios:

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

Não há mais nada relevante em /etc/environmentou /etc/profile.d, os outros arquivos que eu pensei que poderiam ser lidos pelo 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

Também não há nada relevante em nenhum dos arquivos /etc/skel, sem surpresa, nem está sendo definido em nenhum /etc/cron*arquivo:

$ 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

Então, onde está o PATH padrão do cron para crontabs de usuário sendo definido? É codificado em cronsi mesmo? Ele não lê algum tipo de arquivo de configuração para isso?

terdon
fonte
3
Não há razão para cronolhar /etc/profileou se preocupar com qualquer shell em particular. Uma pergunta melhor é por que não cronPATHdo login.defs(no Linux) ou login.conf(no * BSD). Suponho que seja, em última análise, um detalhe de implementação.
Satō Katsura
@ SatōKatsura claro, eu mencionei apenas /etc/profileporque ele usa a mesma sintaxe ( var=value) que cronela mesma, então seria fácil o suficiente e /etc/profileé, que eu sei, muito difundido. O que me surpreendeu é que eu não conseguia encontrá-lo definido em nenhum lugar, então parecia que estava codificado. Como é de fato o caso, como Stephen explicou abaixo.
terdon
As pessoas que usam zshcomo seu shell interativo não se preocupam com /etc/profile(que é específico para bash)
Basile Starynkevitch
2
@BasileStarynkevitch não, que não é específico para bater em tudo ! Pelo contrário! Embora existam alguns shells que não o leem (a família c-shell AFAIK), o zsh não é um deles. Veja a página de manual do zsh, se você não acredita em mim. De qualquer forma, os shells interativos são irrelevantes, pois os vários profilearquivos são lidos apenas pelos shells de login. Estes podem, ou podem não ser interativos.
terdon
1
Às vezes, a execução stringsem um programa também ajuda a encontrar esses valores codificados.
Jrw32982 suporta Monica

Respostas:

47

É codificado no código fonte (esse link aponta para o Debian atual cron- dada a variedade de cronimplementações, é difícil escolher uma, mas outras implementações provavelmente são semelhantes):

#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

cronnão lê caminhos padrão de um arquivo de configuração; Imagino que o raciocínio seja o de que ele suporta a especificação de caminhos que já estão sendo usados PATH=em qualquer cronjob, portanto não há necessidade de especificar um padrão em outro lugar. (O padrão codificado é usado se nada mais especificou um caminho em uma entrada de trabalho .)

Stephen Kitt
fonte
Note que, apesar da existência do _PATH_DEFPATH_ROOTdefine, eu confirmei (usando uma tarefa cron de echo $PATH > /testfile) após editar o crontab do root usando crontab -eno Debian Stretch que o crontab do root também usa _PATH_DEFPATH, ou seja, "/ usr / bin: / bin", não _PATH_DEFPATH_ROOT . Isso também é confirmado pelo segundo link do código-fonte nesta resposta (no qual _PATH_DEFPATH_ROOTnão é usado). Não está claro para mim se essa definição órfã é um bug.
Njahnke
8

Adicionando à resposta de Stephen Kitt, existe um arquivo de configuração que define o PATHcron no Ubuntu e cron ignora o PATHuso do padrão embutido (ou PATHs definido no próprio crontabs). O arquivo é /etc/environment. cronConfiguração do PAM da 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
...

Isso é facilmente verificável. Adicione uma variável para /etc/environment, digamos foo=bar, executar env > /tmp/foocomo um cronjob e observe como foo=baraparece na saída.


Mas por que? O caminho padrão do sistema é definido em / etc / profile, mas isso inclui outros diretórios:

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

Isso é verdade no Arch Linux, mas no Ubuntu, a base PATHestá definida /etc/environment. Arquivos /etc/profile.daderidos a um existente PATHe você pode anexá-lo a ~/.pam_environment. Eu tenho um bug registrado sobre o comportamento de Arch .

Infelizmente, /etc/pam.d/cronnão inclui a leitura de ~/.pam_environment. Estranhamente, /etc/pam.d/atd não incluir esse arquivo:

$ 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

... mas os comandos executados via ataparentemente herdam o ambiente disponível ao criar o attrabalho (por exemplo, env -i /usr/bin/at ...parece executar trabalhos com um ambiente muito limpo).

Alterar /etc/pam.d/cronter user_readenv=1parece não causar problemas, e as variáveis ~/.pam_environmentcomeçaram a aparecer bem (exceto PATH, é claro).


Ao todo, definir variáveis ​​de ambiente para o cron parece ser um negócio confuso. O melhor lugar parece estar na própria especificação do trabalho, apenas porque você não sabe quais variáveis ​​de ambiente herdadas o cron pode decidir ignorar (sem ler a fonte).

muru
fonte
Em relação aos attrabalhos, se você despejar um attrabalho, verá que ele define explicitamente o ambiente para corresponder ao ambiente quando o trabalho foi criado.
Stephen Kitt