2012-04-12 42 views
41

Tôi mới sử dụng công việc lập lịch biểu với cron và crontab. Tôi đang cố gắng lên lịch thực hiện một nhiệm vụ như thể tôi đã đăng nhập, mở một thiết bị đầu cuối và tự thực hiện nó.crontab PATH và USER

Tuy nhiên, tôi lên kế hoạch một nhiệm vụ để giúp tôi quan sát những gì $ USER và $ PATH một nhiệm vụ theo lịch trình được thực hiện với, và đây là những gì tôi tìm thấy:

$ crontab -l 
41 11 * * * echo "USER: $USER" > ~/Desktop/cron_env.log; echo "PATH: $PATH" >> ~/Desktop/cron_env.log 
$ cat ~/Desktop/cron_env.log 
USER: 
PATH: /usr/bin:/bin 

Có vẻ như dù $ USER không được thiết lập , và $ PATH là một cái gì đó rất cơ bản và/hoặc mặc định. Ngược lại, đây là những gì tôi thấy khi mở một terminal (đăng nhập) và echo thông tin này giống nhau:

USER: aschirma 
PATH: /usr/lib/jvm/java-6-sun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/pkg/icetools/bin:/pkg/hwtools/bin:/pkg/netscape/bin:/pkg/gnu/bin 

sao tôi cần phải làm gì để thực hiện nhiệm vụ crontab của tôi chạy theo cách tôi muốn gì?

Trả lời

0

crontab không phải là tập lệnh bash, bạn không thể sử dụng biến môi trường thường có sẵn trong trình bao.

Hãy thử di chuyển tất cả mã đó vào tệp tập lệnh shebang'ed (bắt đầu bằng dòng "#!/Bin/bash") và chạy tập lệnh đó trong crontab.

Tôi không chắc chắn, nhưng tôi nghĩ PATH (và có thể EMAIL nếu bạn đặt) có thể là người duy nhất bạn có thể truy cập bên trong tệp crontab.

EDIT: Kiểm tra crontab 5 man page, có một số biến môi trường đáng tin cậy, tất cả được đặt bởi cron daemon.

+0

OP here. Các tập lệnh được khởi chạy từ cron không kế thừa PATH phù hợp. Trong thực tế, đó là nơi tôi lần đầu tiên bắt đầu chạy vào các vấn đề: một tập lệnh bash được thực hiện từ cron không tìm thấy những thứ trong PATH, bởi vì PATH không chính xác. –

+0

@AdamS Đó là vấn đề, họ kế thừa PATH (và một vài biến khác) được đưa ra bởi cron daemon mà không giống như bạn nhận được từ vỏ đăng nhập của bạn, bạn có thể đặt PATH trong tệp crontab của bạn nếu bạn muốn. – KurzedMetal

+0

Từ manpage: 'Chuỗi giá trị không được phân tích để thay thế môi trường hoặc thay thế biến, do đó các dòng như PATH = $ HOME/bin: $ PATH sẽ không hoạt động như bạn mong đợi.' – blujay

4

Hãy nhớ rằng crontab là một daemon hoặc dịch vụ, vì vậy không giống như người dùng đã đăng nhập hoặc một cái gì đó. Nếu bạn muốn có biến môi trường của bạn, bạn sẽ cần phải đặt chúng mình. Tuy nhiên, hầu hết các biến này được thiết lập bởi trình bao từ đường dẫn/etc/profile và sau đó đi vào các biến tùy chỉnh của bạn vào thư mục $ HOME của bạn.

Bạn có thể thiết lập một số trong số họ bởi "nguồn" của bạn/etc/profile như:

 
41 11 * * * /home/<me>/cron_env.sh 
đâu cron_env.sh sẽ chứa một cái gì đó như:
 
#!/bin/sh 
source /etc/profile 
/usr/bin/env > /home/<me>/cron_env.log 

+0

Tất cả những điều trên không hiệu quả với tôi , Vì vậy, tôi chỉ cần thêm nguồn trong tập tin bash của tôi và nó đã làm việc! Cảm ơn –

15

Trong * ix, quy trình thường được thừa hưởng một môi trường từ quá trình cha mẹ của họ trên fork + exec. Họ có tùy chọn xóa môi trường, nhưng thường thì họ không làm như vậy. Bạn có thể thấy cây quá trình với ps axf, và bạn có thể thấy các biến môi trường bằng cách sử dụng ps axfe.

cron thường không phải là con của shell của ai đó, vì vậy nó thường có môi trường khác với trình bao tương tác của bạn. Có một cơ hội tốt của cron sẽ cố ý xóa bỏ môi trường của mình bằng cách nào đó cho sự nhất quán mặc dù.

Tôi muốn thử nghiệm các công việc cron của tôi ("foo" vì lợi ích của thảo luận) với những điều sau đây trong một vỏ tương tác: env - ./foo Điều này sẽ thực sự rõ ràng hiểu thêm env VAR cron mà không, nhưng nó giúp mọi thứ trở nên dễ dàng hơn với IMO, vì những gì bạn đang thử nghiệm tương tự hơn. Bạn sẽ cần phải thiết lập bất kỳ biến nào bạn đang phụ thuộc vào (như $ PATH), hoặc thay thế chúng bằng cái gì khác - EG $ USER trở thành $ (whoami).

Tôi cũng thích viết các tập lệnh bash của mình để sử dụng "set -eu" và "pipet đặt seto". The -eu nói "thoát trên một mã thoát phizero, và thoát ra trên một tham chiếu biến không xác định", và đường ống nói "không trả lại mã thoát cuối cùng trong một đường ống, thay vào đó trả lại mã thoát đầu tiên không có trong đường ống" . Trong trường hợp của bạn, tập -u có thể đặc biệt hữu ích.

+1

+1 để thử nghiệm ... Tôi 'người đàn ông muốn tìm thông tin về dấu gạch ngang đơn. Tôi ước nó đã được bao gồm trong dòng '-i, --ignore-environment', thay vì ở dưới cùng của phần mô tả, nơi tôi hoàn toàn che đậy nó. –

66

Theo "man 5 crontab" bạn có thể đặt biến môi trường trong crontab của bạn, bằng cách viết chúng trước dòng cron của bạn.

Ngoài ra còn có một ví dụ về một crontab vì vậy bạn chỉ phải sao chép/dán nó:

$ man 5 crontab | grep -C5 PATH | tail 
# and files in /etc/cron.d. These files also have username fields, 
# that none of the other crontabs do. 

SHELL=/bin/sh 
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 

# m h dom mon dow usercommand 
17 * * * * root cd/&& run-parts --report /etc/cron.hourly 
25 6 * * * root test -x /usr/sbin/anacron || (cd/&& run-parts --report /etc/cron.daily) 
47 6 * * 7 root test -x /usr/sbin/anacron || (cd/&& run-parts --report /etc/cron.weekly) 

Vì vậy, bạn có thể điều chỉnh PATH của bạn hoặc bất kỳ biến môi trường để bất cứ điều gì bạn muốn. Nhưng ví dụ này có vẻ đủ cho các trường hợp điển hình.

+6

Có cách nào để làm một cái gì đó như 'PATH = $ PATH:/usr/local/bin'? – CMCDragonkai

+4

@CMCDragonkai: Theo 'man 5 crontab', "Chuỗi giá trị không được phân tích cú pháp để thay thế môi trường hoặc thay thế các biến". Nhưng bạn có lẽ nên viết mã cho bạn trong một tệp thực thi duy nhất ('.sh', nhưng tại sao không phải là C ou Python?), Hãy gọi tệp thực thi của bạn từ crontab, và để cho tệp thực thi tăng thêm $ PATH của nó. –

+0

Điều này đã giải quyết https://community.letsencrypt.org/t/letsencrypt-renew-not-working-with-cronjob-manually-it-works/16738/8 cho tôi. –

2

Trong môi trường của chúng tôi, chúng tôi thường không có vấn đề này như là người chủ là cron chỉ được phép và mỗi lệnh thường được chạy như một người dùng cụ thể ứng dụng VIA lệnh một su -c như:

su - myuser -c "/usr/local/scripts/app.sh" 2>&1 

từ tùy chọn "-" được chỉ định, chúng tôi nhận được hồ sơ và môi trường của myuser. Gần đây chúng tôi đã gặp sự cố với lệnh cần quyền root để hoàn tất thành công, vì vậy chúng tôi vừa ban hành lệnh mà không có lệnh su -c. Sau một số nghiên cứu, chúng tôi thấy rằng cách dễ nhất để có môi trường gốc là sử dụng cùng một kỹ thuật cho root như chúng tôi đã làm cho tất cả các ứng dụng khác, do đó chúng tôi đã phát hành: