Làm thế nào tôi có thể chạy một lệnh cron với các biến môi trường hiện có?


114

Làm thế nào tôi có thể chạy một lệnh cron với các biến môi trường hiện có?

Nếu tôi đang ở dấu nhắc shell, tôi có thể nhập echo $ORACLE_HOMEvà nhận đường dẫn. Đây là một trong những biến môi trường của tôi được đặt trong tôi ~/.profile. Tuy nhiên, có vẻ như ~/.profilekhông được tải tập lệnh fron cron và vì vậy tập lệnh của tôi thất bại vì $ORACLE_HOMEbiến không được đặt.

Trong câu hỏi này , tác giả đề cập đến việc tạo một ~/.cronfilehồ sơ thiết lập các biến cho cron, và sau đó anh ta thực hiện một cách giải quyết để tải tất cả các lệnh cron của mình vào các tập lệnh mà anh ta giữ trong ~/Cronthư mục của mình . Một tập tin ~/.cronfilenghe có vẻ như là một ý tưởng tốt, nhưng phần còn lại của câu trả lời có vẻ hơi cồng kềnh và tôi đã hy vọng ai đó có thể cho tôi biết một cách dễ dàng hơn để có được kết quả tương tự.

Tôi cho rằng khi bắt đầu các kịch bản của mình, tôi có thể thêm một cái gì đó như thế source ~/.profilenhưng có vẻ như nó có thể là dư thừa.

Vậy làm thế nào tôi có thể làm cho các tập lệnh cron của tôi tải các biến từ hồ sơ shell tương tác của tôi?


Làm thế nào là thêm source ~/.profilevào một chương trình dư thừa? Các chương trình kế thừa môi trường của họ từ chương trình gọi. Nếu chương trình gọi đó không phải là vỏ của bạn, thì chương trình bị cáo sẽ có được môi trường mà bạn muốn như thế nào?
Arcege

Tôi đã viết câu trả lời của mình cho một câu hỏi tương tự ở đây. Nó chỉ đơn giản là sử dụng su -lđể thiết lập một môi trường đăng nhập bình thường bao gồm $ PATH cho người dùng root hoặc người dùng cụ thể khác.
nhiệm vụ

Câu trả lời:


141

Trong crontab, trước khi bạn ra lệnh, hãy thêm . $HOME/.profile. Ví dụ:

0 5 * * * . $HOME/.profile; /path/to/command/to/run

Cronkhông biết gì về vỏ của bạn; nó được khởi động bởi hệ thống, vì vậy nó có một môi trường tối thiểu. Nếu bạn muốn bất cứ điều gì, bạn cần phải có điều đó mang trong mình.


14
Những gì .trước khi kịch bản làm gì? (không chắc làm thế nào tôi sẽ làm manđiều đó). Tại sao điều này khác với source?
cwd

25
Các .lệnh là lệnh ban cho source. Chúng tương đương trong vỏ và dễ gõ hơn một chút, đặc biệt là trong crontab. Để có thêm thông tin, hãy nhập help .hoặc tìm kiếm ^SHELL BUILTIN COMMANDStrong trang man cho bashhoặc ở đầu loại man zshbuiltins . Running .` sẽ cho bạn biết rằng lệnh là một lệnh dựng sẵn.
Arcege

9
Tùy thuộc vào bản phân phối Linux, bạn có thể cần thay đổi .profiletheo .bash_profile. Kiểm tra .profiletập tin nào tồn tại trong thư mục nhà của người dùng.
Frosty Z

@Arcege Điều này không phù hợp với tôi (Fedora Core 21) và tôi cho rằng đó là do mức độ vỏ giảm xuống. Thay vào đó, những gì DOES hoạt động là nếu bạn nguồn nó.
Richard T

3
Có khả năng là nếu nó không hoạt động, thì đó là vì SHELL cho tập lệnh cron không được đặt thành bash, vì vậy nó không thực thi theo cách bạn mong đợi.
Daniel Farrell

40

Một tùy chọn khác, mà tôi thấy dễ dàng hơn, là chạy tập lệnh với cron và có môi trường trong tập lệnh.

Trong tập tin crontab -e:

SHELL=/bin/bash

*/1 * * * * $HOME/cron_job.sh

Trong tệp cron_job.sh:

#!/bin/bash
source $HOME/.bash_profile
some_other_cmd

Bất kỳ lệnh nào sau nguồn .bash_profile sẽ có môi trường của bạn như thể bạn đã đăng nhập.


5
Khi chạy trên AWS Linux AMI, tôi thậm chí còn không biết rằng cron sẽ không được sử dụng /bin/bashlàm vỏ. Tôi cứ tự hỏi tại sao những thứ như thế cd /path/to/project; source .varssẽ hoạt động khi tôi gõ chúng bằng tay nhưng sẽ thất bại ( File not found) khi được đưa vào một cronjob. Dòng quan trọng đối với tôi là thiết lập SHELL=/bin/bashđể tôi thực sự có thể sử dụng các lệnh bash quen thuộc trong mỗi cronjob. /bin/sh/(vỏ cron mặc định, rõ ràng) là rất hạn chế.
Hartley Brody

Thật tệ khi bạn không thể chỉ định Tệp Môi trường ở đầu cron như bạn có thể chỉ định các biến môi trường riêng lẻ. Systemd có một EnvironmentFileđơn vị dịch vụ. Cron quá xấu không có cái gì đó tương tự.
radtek

bạn FORCE tất cả các tập lệnh để sử dụng / bin / bash trong tất cả các crontab, đó không phải là một ý tưởng hay, còn về dòng cron của bạn: * / 1 * * * * $ HOME / cron_job.shọ * / 1 là tốt cho CÁI GÌ ?!? một ngôi sao có nghĩa là nó sẽ bị xử tử mỗi phút / 1 nghĩa là sẽ bị xử tử mỗi phút, vì một câu trả lời trong một cộng đồng thông minh đây là một tội lỗi khó chịu, bây giờ tôi tin rằng bạn rất bối rối khi nói lời xin lỗi hay nhất
THESorcerer

1
Đây là những gì được gọi là một ví dụ. Hãy thoải mái điều chỉnh theo nhu cầu của bạn hoặc không sử dụng nó. Vạn người vạn nét.
Robert Brisita

4
Nếu $SHELL/bin/sh, sourcelệnh không tồn tại. Sử dụng .thay thế.
Melle

18

Một tùy chọn khác, mà tôi thấy dễ dàng hơn, là chạy tập lệnh với cron và báo bash để đăng nhập (do đó sử dụng /etc/profile.d/...định nghĩa môi trường)

Trong crontab -etập tin:

*/1 * * * * bash -l -c './cron_job.sh'
*/1 * * * * bash -l -c 'php -f ./cron_job.php'

Bất kỳ lệnh nào sau nguồn .bash_profilesẽ có môi trường của bạn như thể bạn đã đăng nhập.


10

Ý kiến ​​tồi. Thực tiễn chung là đặt cụ thể tất cả các biến môi trường cần thiết trong một tập lệnh sẽ được chạy từ một công việc định kỳ.


Tôi đồng ý với @fpmurphy, theo cách đó nó cũng đảm bảo môi trường quy trình được bảo mật. Nếu bạn muốn chỉ đặt một vài biến từ cron, bạn có thể sử dụng /usr/bin/envlệnh để đặt các biến và sau đó có thể đóng vai trò là quá trình môi trường cho cronjob.
Nikhil Mulley

daemontools 'cũngenvdir đến với tâm trí.
sr_

6
Tôi là tất cả để bảo mật, nhưng có lẽ tôi có thể tạo một tệp ~/.cronvarsvà bao gồm nó trong hồ sơ và cả trong các tập lệnh cron của tôi. Tôi không muốn mã cứng biến môi trường trong mỗi tập lệnh tôi chạy vì khi đường dẫn thay đổi đường dẫn được mã hóa cứng trong mỗi tệp không dễ duy trì. Có vẻ như điều đó sẽ cho phép một nơi tập trung cho các biến cần thiết và vẫn giữ cho các biến khác không được tải.
cwd

4

Cú pháp này chắc chắn giúp bạn. Tôi không hiểu cú pháp, nhưng nó hoạt động. Oracle sử dụng cú pháp này, khi triển khai Trình quản lý cấu hình Oracle cho crontab, do đó, tôi tin rằng đây là một giải pháp đúng.

0 5 * * * SOME_ENV_VAR=some_value some_command some_parameters

2

Gần đây tôi đã gặp một trường hợp tôi phải thực thi cronjob tổng thể với quyền root, nhưng đồng thời, phải thực thi một tiểu ban với tư cách là một người dùng khác (yêu cầu tìm nguồn cung ứng môi trường của người dùng đó). Tôi đã đi với cách tiếp cận sau:

# m  h  dom  mon  dow  user  command
*/5  *   *    *    *   root  (sudo -i -u <the user> command-to-be-run-as-user) && command-to-be-run-as-root

Phần quan trọng là đối số -iđược truyền vào sudosẽ thực thi lệnh đã cho trong một vỏ đăng nhập riêng (điều này có nghĩa là các dotfiles của người dùng sẽ có nguồn gốc).

PS: Lưu ý rằng usercột chỉ có sẵn trong /etc/crontabvà các /etc/cron.d/*tệp.


1

Các giải pháp, làm việc cho tôi, được mô tả ở đây .

Bạn tạo một tập lệnh bao bọc, gọi . ~/.cronfilevà sau đó thực hiện những điều bạn muốn. Kịch bản này được khởi chạy bởi cron.

Trong ~/.cronfilebạn chỉ định môi trường cho công việc cron của bạn.


1

Có, bạn có thể sử dụng "cách giải quyết nổi tiếng" (một vài trong số đó đã được liệt kê). Đây là một cách khác để nói rằng mọi người đều biết nó thật vớ vẩn, mặc dù một số người sẽ coi đây là một "tính năng bảo mật" bởi vì họ đã dành ít nhất nhiều lần vấp phải sự thất bại này (ure) như bạn có, và muốn nghĩ về họ lãng phí thời gian không phải là vô ích. Đây là cron tương đương với bàn phím QWERTY.

Tôi nghi ngờ lý do ban đầu có thể là vì hiệu suất, vì vậy các tập lệnh chạy một lần một phút sẽ không dành thời gian để đọc các tập lệnh RC. Ngoài ra, cron ban đầu hoàn toàn không thể cấu hình được, vì vậy mặc định thực sự là lựa chọn duy nhất.

Không có bảo mật bổ sung bằng cách không có một số cấu hình hoặc phương pháp đơn giản để có cron chỉ sử dụng môi trường của vỏ tương tác của bạn thay vì người dùng phải thực hiện thể dục dụng cụ vỏ ngu ngốc. Trên một máy hiện đại thường không có hiệu suất rõ rệt trừ khi bạn có một lượng lớn công việc chạy mỗi phút.

Văn hóa Unix thất bại. Theo ý kiến ​​"khiêm tốn" của tôi. :-)


1
"Không có bảo mật bổ sung." Điều đó không đúng. Hãy xem CVE-2011-1095 , CVE-2008-4304CVE-2010-3847 .

Nhân tiện, tôi đã đánh giá thấp câu trả lời của bạn. Tôi thường cố gắng tránh hạ thấp câu trả lời của người mới nhưng bảo mật rất quan trọng đối với tôi. Xin đừng dùng downvote sai cách. Bên cạnh phần về bảo mật, câu trả lời của bạn là tuyệt vời và sẽ xứng đáng được nâng cấp. Bạn có thể chỉnh sửa câu trả lời của bạn ở đây nếu bạn muốn.

Không ai trong số họ có điều nhỏ nhất để làm với cron sử dụng shell với bộ cờ tương tác. Đây là FUD thuần túy. Thật không may, tôi không thể downvote downvote của bạn. Điều này có vẻ giống như một ngọn lửa, nhưng thật bực bội khi mọi người nghĩ rằng một chiếc xe có ba bánh là tốt hơn bởi vì có một vấn đề an ninh để đặt một bánh xe thứ tư. Không phải vậy. Mọi người chỉ lái một chiếc xe ba bánh quá lâu nên họ đã quên mất việc có thể thêm một bánh xe thứ tư.
Austin S.

Đặt một cách khác: nếu bất kỳ một trong số các vòng bổ sung dự định mà những người trả lời khác được đề xuất được sử dụng, làm thế nào để họ cũng không có quyền truy cập vào bất kỳ lỗ hổng nào bạn đề cập? "* * * * * exec bash -i -c LOCALE = ......."
Austin S.

Điều này đọc như một lời nói. Tôi thậm chí không thấy nơi nó trả lời câu hỏi. Ngay cả khi phần bảo mật đã bị xóa, @EvanTeitelman, tôi không hiểu tại sao nó lại xứng đáng được nâng cấp vì nó không trả lời câu hỏi.
tự đại diện


1

Thay vì thiết lập hồ sơ, những gì đã giúp tôi là thiết lập PATH. Một số lệnh không có sẵn trong tập lệnh cron của tôi vì PATHnó khác.

ENVIRONMENT=prod
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/30 * * * * /opt/myscript1.sh
*/30 * * * * /opt/myscript2.sh
*/30 * * * * /opt/myscript3.sh

Thiết lập PATHvới đường dẫn của các lệnh đã giúp tôi. Thậm chí tốt hơn nếu bạn có thể sử dụng một mẫu và phát hiện ra sau này,

ENVIRONMENT={{ENVIRONMENT}}
PATH={{PATH}}
*/30 * * * * /opt/myscript1.sh
*/30 * * * * /opt/myscript2.sh
*/30 * * * * /opt/myscript3.sh

Truyền biến cho từng mục trông lộn xộn.


-1

Tôi đặt . ~/.dbus/session-bus/*ở đầu tập lệnh mong muốn của tôi :)


1
Chào mừng bạn đến với U & L SE. Vui lòng mở rộng câu trả lời của bạn nhiều hơn để nó sẽ có lợi cho độc giả.
Ramesh
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.