Bộ PATH của cron nằm ở đâu?


34

Cron không sử dụng đường dẫn của người dùng có crontab và thay vào đó, có đường dẫn riêng. Nó có thể dễ dàng thay đổi bằng cách thêm PATH=/foo/barvào đầu crontab và cách giải quyết cổ điển là luôn luôn sử dụng các đường dẫn tuyệt đối đến các lệnh được chạy bởi cron, nhưng PATH mặc định của cron được định nghĩa ở đâu?

Tôi đã tạo một crontab với các nội dung sau trên hệ thống Arch của tôi (cronie 1.5.1-1) và cũng đã thử nghiệm trên hộp Ubuntu 16.04.3 LTS với kết quả tương tự:

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

Nó được in:

$ cat fff
/usr/bin:/bin

Nhưng tại sao? Đường dẫn toàn hệ thống mặc định được đặt /etc/profile, nhưng bao gồm các thư mục khác:

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

Không có gì khác có liên quan trong /etc/environmenthoặc /etc/profile.d, các tệp khác mà tôi nghĩ có thể được đọc bởi 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

Không có gì có liên quan trong bất kỳ tệp nào trong /etc/skel, không ngạc nhiên, cũng không được đặt trong bất kỳ /etc/cron*tệp nào :

$ 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

Vậy, PATH mặc định của cron cho crontabs của người dùng được đặt ở đâu? Có phải nó được mã hóa cứng trong cronchính nó? Nó không đọc một số loại tập tin cấu hình cho điều này?


3
Không có lý do cronđể xem xét /etc/profile, hoặc quan tâm đến bất kỳ vỏ cụ thể. Một câu hỏi hay hơn là tại sao không cronđọc PATHtừ login.defs(trên Linux) hoặc login.conf(trên * BSD). Tôi cho rằng cuối cùng nó là một chi tiết thực hiện.
Satō Katsura

@ SatōKatsura chắc chắn, tôi chỉ đề cập /etc/profilevì nó sử dụng cùng một cú pháp ( var=value) như cronchính nó, vì vậy nó sẽ đủ dễ để làm và /etc/profile, theo hiểu biết của tôi, rất phổ biến. Điều làm tôi ngạc nhiên là tôi không thể tìm thấy nó được đặt ở bất cứ đâu nên có vẻ như nó được mã hóa cứng. Thực sự là như vậy, như Stephen giải thích dưới đây.
terdon

Những người sử dụng zshlàm vỏ tương tác của họ không quan tâm /etc/profile(cụ thể là bash)
Basile Starynkevitch

2
@BasileStarynkevitch không, nó không cụ thể để bash chút nào ! Hoàn toàn ngược lại! Mặc dù có một số shell không đọc nó (họ c-shell AFAIK), zsh không phải là một trong số chúng. Xem trang chủ zsh, nếu bạn không tin tôi. Trong mọi trường hợp, shell tương tác là không liên quan vì dù sao các profiletệp khác nhau chỉ được đọc bởi shell đăng nhập. Đây có thể, hoặc có thể không tương tác.
terdon

1
Đôi khi chạy stringsvới một chương trình cũng có thể giúp tìm thấy các giá trị được mã hóa cứng này.
jrw32982 hỗ trợ Monica

Câu trả lời:


47

Nó được mã hóa cứng trong mã nguồn (liên kết đó trỏ đến Debian hiện tại cron- với nhiều cách crontriển khai khác nhau , thật khó để chọn một mã, nhưng các triển khai khác có thể tương tự nhau):

#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

cronkhông đọc đường dẫn mặc định từ tệp cấu hình; Tôi tưởng tượng lý do là nó hỗ trợ chỉ định các đường dẫn đã sử dụng PATH=trong bất kỳ cronjob nào, vì vậy không cần phải chỉ định mặc định ở nơi khác. (Mặc định được mã hóa cứng được sử dụng nếu không có gì khác chỉ định đường dẫn trong mục nhập công việc .)


Lưu ý rằng, mặc dù có sự tồn tại của _PATH_DEFPATH_ROOTđịnh nghĩa, tôi đã xác nhận (sử dụng công việc định kỳ echo $PATH > /testfile) sau khi chỉnh sửa crontab của root bằng cách sử dụng crontab -eDebian Stretch mà crontab của root cũng sử dụng _PATH_DEFPATH, tức là "/ usr / bin: / bin", không _PATH_DEFPATH_ROOT . Điều này cũng được xác nhận bởi liên kết mã nguồn thứ hai trong câu trả lời này ( _PATH_DEFPATH_ROOTkhông được sử dụng). Tôi không rõ liệu định nghĩa mồ côi này có phải là một lỗi hay không.
njahnke

8

Thêm vào câu trả lời của Stephen Kitt, có một tệp cấu hình đặt PATHcron trên Ubuntu và cron bỏ qua việc PATHsử dụng mặc định được mã hóa cứng (hoặc PATHđược đặt trong chính crontabs). Các tập tin là /etc/environment. cronCấu hình PAM của Note :

$ 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
...

Điều này dễ dàng kiểm chứng. Thêm một biến vào /etc/environment, giả sử foo=bar, chạy env > /tmp/foonhư một cronjob và xem như foo=barhiển thị trong đầu ra.


Nhưng tại sao? Đường dẫn toàn hệ thống mặc định được đặt trong / etc / profile, nhưng bao gồm các thư mục khác:

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

Điều đó đúng trong Arch Linux, nhưng trong Ubuntu, cơ sở PATHđược đặt trong /etc/environment. Tập tin trong /etc/profile.dtack vào một hiện PATH, và bạn có thể thêm nó vào ~/.pam_environment. Tôi có một lỗi gửi về hành vi của Arch .

Thật không may, /etc/pam.d/cronkhông bao gồm đọc từ ~/.pam_environment. Thật kỳ lạ, /etc/pam.d/atd bao gồm tập tin đó:

$ 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

... nhưng các lệnh chạy thông qua atrõ ràng kế thừa môi trường có sẵn khi tạo atcông việc (ví dụ, env -i /usr/bin/at ...dường như chạy các công việc với môi trường rất sạch).

Sửa đổi /etc/pam.d/cronđể có user_readenv=1dường như không gây vấn đề, và các biến trong ~/.pam_environmentbắt đầu xuất hiện tốt (trừ PATH, tất nhiên).


Tất cả đã nói, thiết lập các biến môi trường cho cron dường như là một công việc lộn xộn. Vị trí tốt nhất dường như nằm trong chính đặc tả công việc, nếu chỉ vì bạn không biết biến môi trường được kế thừa nào mà cron có thể quyết định bỏ qua (mà không cần đọc nguồn).


Về atcông việc, nếu bạn bỏ một atcông việc, bạn sẽ thấy công việc đó rõ ràng đặt môi trường phù hợp với môi trường khi công việc được tạo.
Stephen Kitt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.