cron bỏ qua các biến được định nghĩa trong, .bashrc, và .bash_profile,


49

Tôi đã xác định biến "SHELL" trong tệp / etc / crontab:

[martin@martin ~]$ grep SHELL /etc/crontab 
SHELL=/usr/local/bin/bash
[martin@martin ~]$ file /usr/local/bin/bash
/usr/local/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 8.0 (800107), stripped
[martin@martin ~]$ 

Ngoài ra, tất cả các tập lệnh của tôi trong tệp / etc / crontab được bắt đầu dưới người dùng "martin". Tuy nhiên /home/martin/.bash_profile (đối với vỏ đăng nhập) và /home/martin/.bashrc (đối với vỏ phi-logging) chứa một số biến mà được bỏ qua trong trường hợp của công việc định kỳ, nhưng được sử dụng trong trường hợp tôi đăng nhập vào máy qua SSH hoặc mở phiên bash mới. Tại sao cron bỏ qua các biến đó? Không phải cron chỉ đơn giản là thực thi "/ usr / local / bin / bash my-script.sh" với quyền cho người dùng "martin"?


2
Người dùng Ubuntu có thể muốn lưu ý rằng mặc định của Ubuntu .bashrcmột dòng ngăn không cho nó chạy trong các vỏ không tương tác.
joeytwiddle

Câu trả lời:


72

Bạn có thể nguồn tệp bạn muốn ở đầu tập lệnh hoặc bắt đầu công việc cho người dùng đang thực hiện công việc. Lệnh "nguồn" được tích hợp sẵn. Bạn sẽ làm điều tương tự nếu bạn chỉnh sửa các tệp đó để tải các thay đổi.

* * * * * source /home/user/.bash_profile; <command>

hoặc là

#!/bin/bash
source /home/user/.bash_profile

<commands>

2
Lưu ý rằng "nguồn" có thể không hoạt động nếu cron không sử dụng bashshell. Tôi đã thêm một câu trả lời có thể xử lý trường hợp khi vỏ sh.
Jonathan


23

Bởi vì nó không phải là một vỏ tương tác. Điều tương tự xảy ra khi bạn mở một số thiết bị đầu cuối.

Hãy xem câu hỏi này: Tệp .bashrc là gì? | Siêu người dùng

Và cũng tại đây:

Sự khác biệt giữa .bashrc, .bash_profile và .envir là gì? | Tràn ngăn xếp

Các tập lệnh khác nhau kích hoạt tùy thuộc vào việc kết nối là vỏ đăng nhập (hoặc không), vỏ tương tác (hoặc không) hoặc cả hai.

Nếu bạn muốn tạo bashrc, bạn cần thực hiện thay đổi này:

Ví dụ, khi Bash được khởi động không tương tác, để chạy tập lệnh shell, nó tìm biến BASH_ENV trong môi trường, mở rộng giá trị của nó nếu nó xuất hiện ở đó và sử dụng giá trị mở rộng làm tên của tệp để đọc và thực thi . Bash hành xử như thể lệnh sau được thực thi:

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi 

nhưng giá trị của biến PATH không được sử dụng để tìm kiếm tên tệp.

Như đã lưu ý ở trên, nếu một shell không tương tác được gọi với --logintùy chọn, Bash cố gắng đọc và thực thi các lệnh từ các tệp khởi động shell đăng nhập.

Nguồn: Bash Startup Files | Tài liệu tham khảo Bash | gnu.org


Vì vậy, nếu chúng ta đặt BASH_ENV bên trong Cron, các tập lệnh cron bash sẽ lấy nguồn đó vì cron không tương tác và không đăng nhập.
CMCDragonkai

12

Bạn có thể không chạy được sourcenếu shvỏ đang được sử dụng. Điều này có thể được thay đổi bằng cách thêm dòng sau vào crontab của bạn:

SHELL=/bin/bash
* * * * * source "/root/.bashrc"; <command>

Bạn cũng có thể chỉ định môi trường:

BASH_ENV="/root/.bashrc"
* * * * * <command>

hoặc bạn có thể sử dụng cục bộ của mình /home/user/.bashrcnếu đó là công việc định kỳ của người dùng (ví dụ crontab -e).

Lưu ý rằng .bash_profilecó thể thay thế .bashrc, nếu nó tồn tại.

Tín dụng: Làm thế nào để thay đổi cron shell (sh thành bash)?


điều này cũng hoạt động tốt đối với các công việc được lên lịch của Cloud Cloud, về cơ bản là các công việc định kỳ. Bạn có thể làm tương tự, như:SHELL=/bin/bash && source /home/YOUR_USER_NAME/.bash_profile && sh ....
Alejandro Moreno

1

Một cái gì đó khác có thể can thiệp vào việc tìm nguồn cung ứng của bạn .bashrctừ một cronjob là bất kỳ kiểm tra nào mà tệp này thực hiện để phát hiện các vỏ tương tác.

Ví dụ: trên Ubuntu 18.04, mặc định .bashrccho người dùng bắt đầu bằng điều này:

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

và vì vậy, nó sẽ không làm gì hữu ích vì nó sẽ thoát ra ngay lập tức.


1

Bạn có thể gọi bash với -ltùy chọn, như thế này:

* * * * * /bin/bash -l /path/to/script arg1 arg2

Các -ltùy chọn làm cho bash một login shell. Vì vậy, nó sẽ đọc người dùng .bash_profile. Nó sẽ không đọc người dùng .bashrctrừ khi nó có nguồn gốc rõ ràng .bash_profile. Điều này là do các vỏ không tương tác không tự động đọc .bashrc. Nhưng bạn không cần .bashrcmột công việc định kỳ vì .bashrcđể thiết lập những thứ hữu ích cho trình bao tương tác .

Biến thể:

Nếu bash nằm trên PATH, không cần chỉ định đường dẫn tuyệt đối:

* * * * * bash -l /path/to/script arg1 arg2

Tối ưu hóa sẽ là thay thế shell hiện tại bằng cách sử dụng exec:

* * * * * exec bash -l /path/to/script arg1 arg2

1

bashhành động khác nhau cho dù đó là vỏ hay ngôn ngữ lập trình bình thường (như perlhoặc python).

Theo thiết kế, các cài đặt trong ~/.bash_profile, ~/.bashrcv.v. dành cho người dùng để đặt mọi thứ khi bashđóng vai trò của trình bao (vỏ đăng nhập, vỏ xen kẽ). Hãy suy nghĩ về môi trường bạn có trong xterm(vỏ tương tác) hoặc trong sshphiên (vỏ đăng nhập) hoặc trong bảng điều khiển (vỏ đăng nhập).

Mặt khác, bashcũng là một ngôn ngữ progamming mạnh mẽ , rất nhiều về các kịch bản để quản lý các dịch vụ systemd- đòi hỏi một phong cách làm việc khác. Ví dụ: khi nhà phát triển đang viết kịch bản hệ thống hoặc bashchương trình, anh ấy / cô ấy sẽ không muốn tự động lấy nguồn của người dùng ~/.bash_profile. Nó là một chương trình bình thường, không phải là một vỏ. Một chương trình bình thường (bao gồm bashcác chương trình) sẽ tự nhiên kế thừa các cài đặt từ chế độ làm việc hiện tại (shell), nhưng không đặt chúng.

Nếu chúng ta viết một chương trình cho crontrong bash-nó chỉ xảy ra phải được viết bằng bash; trên thực tế, chúng ta có thể viết nó trong pythonhoặc perlhoặc bất kỳ progamming khác vào ngôn ngữ thì chúng ta có thể có một tùy chọn để nguồn bash's ~/.bash_profile(đọc: thiết lập của vỏ của người dùng, mà chỉ xảy ra được cùng một ngôn ngữ của ngôn ngữ lập trình của bạn):

[ -f /home/user/.bash_profile ] && . /home/user/.bash_profile

Tuy nhiên, nếu người dùng cụ thể đó không sử dụng bashlàm vỏ của họ thì sao? Ông / bà có thể sử dụng zsh, ksh, fish, vv Vì vậy, thực tế có thể sẽ không thực sự làm việc khi viết chương trình cho mục đích công.

Vì vậy, bạn có thể nguồn ~/.bash_profilenếu bạn nghĩ rằng nó sẽ làm việc. Nhưng, ở đây, không phải là về việc chúng ta có thể tìm nguồn một tệp hay không, mà là về cách mọi thứ nên hoạt động trong hệ thống: khái niệm thiết kế . Tóm lại: chúng ta nên xem bashnhư một cái gì đó có 2 vai trò: ngôn ngữ shell và progamming . Rồi mọi thứ sẽ dễ hiểu hơn nhiều.


0

Tôi gặp vấn đề tương tự khi thực hiện một ứng dụng nút từ cron sử dụng NVM, Để tạo bash shell để đọc tệp .bashrc từ cron, chỉ cần liệt kê lệnh bash với tùy chọn shell tương tác `-l.

ví dụ: * * * * * /bin/bash -lc '/home/user/myapp.sh restart'

Nếu không được, hãy thử đặt biến đường dẫn trong crontab

41 7 * * * /bin/bash -lc "PATH=$PATH:/home/user/.nvm/versions/node/v8.10.0/bin && /home/user/script.sh restart "

-1

Cách của tôi để đối phó với nó là:

1) Đưa các biến của tôi vào (cuối của) ~/.profile:

myVarInDotProfile="someValue"

2) Tạo tập lệnh Bash cho các tác vụ cron (hàng ngày) ~/cronDaily.shcủa tôi ( ) chứa các lệnh của tôi cộng với tìm nguồn lặp lại của ~/.profle:

source ~/.profile
command ${myVarInDotProfile}/

3) lên lịch thực hiện kịch bản của tôi từ crontab, để chạy hàng ngày:

0 0 * * * bash ~/cronDaily.sh

Biến của tôi không bị bỏ qua và các lệnh đã chạy thành công.


Một số có thể nói nguồn cung cấp mạnh mẽ như vậy ~/.profilelà có vấn đề. Trong trường hợp cụ thể của tôi, tôi không thấy lý do tại sao nó là một vấn đề nhưng tôi sẽ khuyên bạn nên xem xét việc tạo một tệp dành riêng cho điều đó.

Nói chung, có thể có một cách tốt hơn cho vấn đề này nhưng đó là điều làm việc cho tôi sau rất nhiều đau đớn và nó giải thích nguyên tắc rằng kể từ Bash 4.3.46, bạn không thể lấy một tệp từ đó crontab.

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.