Shell mặc định cho vấn đề cron


8

Tôi có một số lệnh, chúng đang làm việc theo bash, nhưng không phải là cronjob. Để xem, nguyên nhân gây ra sự cố, tôi đang lưu kết quả đầu ra trong một tệp, đây là ví dụ của tôi:

51  *  *   *   *    source ~/.rvm/scripts/rvm >> stack.log 2>&1

Nội dung của tệp nhật ký là:

/bin/sh: 1: source: not found

Điều đó có nghĩa là, cron đang sử dụng shinsead của bash. Tôi đã cố gắng thay đổi nó trong /etc/crontab:

SHELL=/bin/bash

Nhưng điều này không làm việc. Tôi đã nhìn vào /etc/passwdvà ở đây tôi thấy, daemon đang sử dụng shlàm vỏ mặc định. Cả hai rootpibashvỏ mặc định.

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
pi:x:1000:1000:,,,:/home/pi:/bin/bash

Tôi nên làm gì để thay đổi shell mặc định cho cron? Tôi sẽ không thiết lập /bin/bashcho người dùng daemon trong /etc/passwd... imho đây không phải là một ý tưởng tốt.

chỉnh sửa :

ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30  2012 /bin/sh -> dash

đây là nội dung của /etc/crontab:

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

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

# m h dom mon dow user  command
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 )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#

1
Tại sao bạn muốn sourcetrong môi trường crons? Đơn giản chỉ cần chạy ~/.rvm/scripts/rvmkhông hoạt động? Và bạn có thể gặp vấn đề với việc sử dụng ~ trong môi trường không có bash.
macrojames

Câu trả lời:


4

Vỏ được sử dụng là dash; một vỏ tương thích POSIX, được thiết kế nhỏ hơn và ổn định hơn nhiều bash.

Người ta có thể lập luận rằng bạn nên viết croncông việc để tuân thủ POSIX. Ngoài ra, hãy thử gói logic của bạn vào một tập lệnh và chuẩn bị shebang

#!/usr/bin/env bash

2
tại sao #! / usr / bin / env bash mà không #! / bin / bash? Sự khác biệt là gì?
cupakob

1
IMHO không nhiều. Nói đúng ra, nó cho phép bashđược lưu trữ ở nơi khác. Ai sẽ làm điều đó, tôi không biết!
Alex Chamberlain

Tôi cũng đã thử điều này ... tôi có một tập lệnh bash Wrapper, gọi lệnh của tôi, nhưng điều này cũng không hoạt động. Nhưng tôi đang đi lang thang, tại sao những thay đổi trong / etc / crontab không làm cho swich thành bash.
cupakob

@cupakob Bạn có thể dán toàn bộ /etc/crontabkhông?
Alex Chamberlain

1
Tôi nghĩ vấn đề là sourcemột nội trang, không có nghĩa gì để chạy theo đúng nghĩa của nó.
Alex Chamberlain

4

Hầu hết các trường hợp như vậy (trong đó script hoạt động trong shell nhưng không phải trong cron) là do các biến môi trường khác nhau trong script. Trong nhiều trường hợp các vấn đề là PATHbiến. Bạn có thể sử dụng đường dẫn đầy đủ cho tất cả các tệp thực thi mà bạn đang chạy trong tập lệnh hoặc sửa đổi PATHtrong dòng đầu tiên của tập lệnh.

Để theo dõi các vấn đề như vậy, bạn có thể bắt đầu từ việc bỏ các biến môi trường có sẵn cho tập lệnh của mình bằng cách sử dụng envlệnh, như sau: / usr / bin / env> /tmp/env.txt


tôi không có bất kỳ biến môi trường nào trong tập lệnh của mình ... và / bin / env không tồn tại.
cupakob

2
Không, bạn luôn có một số biến môi trường trong mỗi vỏ. Một ví dụ là PATHđã được đề cập. Hãy thử /usr/bin/envthay thế. Hoặc sử dụng which envđể kiểm tra xem đường dẫn đầy đủ của bạn là gì env.
Krzysztof Adamski

3

Bạn có chắc chắn rằng sourcingkịch bản của bạn cronhoàn toàn là những gì bạn muốn làm và quan trọng hơn là cần thiết? Tôi nghĩ rằng nó hầu như luôn luôn là một ý tưởng tồi.

Ngoài ra, khi bạn đang chỉnh sửa cron(cũng như các công cụ khác có thể được khởi chạy bởi người dùng khác và / hoặc các trình bao khác), hãy thử thực hiện một cách tiếp cận từng bước. Ví dụ: bạn có thể kiểm tra môi trường của mình bằng một cái gì đó như thế này:

42  *  *   *   *    bash -c "echo home---$HOME---"   >> /tmp/cron-temp.log 2>&1
42  *  *   *   *    bash -c "echo shell---$SHELL---" >> /tmp/cron-temp.log 2>&1

hoặc thậm chí:

42  *  *   *   *    bash -c "export"                 >> /tmp/cron-temp.log 2>&1

Vì vậy, bạn có thể có bằng chứng về môi trường của bạn, vv

Để trả lời câu hỏi của bạn, tôi sẽ không thay đổi vỏ cho cron. Tôi chỉ đơn giản là bảo nó gọi bashvà sau đó bashgọi kịch bản của bạn.


$ SHELL vẫn là 'sh' mặc dù tôi đã thay đổi nó trong / etc / crontab
cupakob

1
Vâng, đó cũng là mặc định trong tôi cron. Như tôi đã nói, tôi sẽ không thay đổi nó. Chỉ cần gọi cho kịch bản của bạn thông qua bashvới bash -c "yourscript"và tất cả mọi thứ nên được tốt (không nguồn kịch bản của bạn, bạn có thể không cần nó!)
Avio

vâng, điều này sẽ hoạt động, nhưng tôi muốn biết, tại sao shell mặc định không được thay đổi.
cupakob

3

Vì vậy, .... tôi có hai giải pháp cho vấn đề của mình:

  1. Kịch bản lệnh Wrapper qua lệnh bash, hiện tại tôi đang gọi là cronjob. Vấn đề ở đây - đối với mỗi cronjob tôi cần một trình bao bọc, và đây không phải là cách giải quyết tốt nhất cho tôi.

  2. Tôi đã cố gắng gọi một kịch bản ruby ​​là cronjob. Điều này không hoạt động, vì vậy tôi nghĩ, tôi cần gọi 'rvm sử dụng 1.9.3' và trước tiên tôi cần gọi 'source ~ / .rvm / scripts / rvm'. Và đây là sai lầm của tôi. Trong ví dụ bash của tôi, tôi có đường dẫn đến ruby, nhưng không phải là cron. Sau khi tôi sửa lỗi này, mọi thứ đều hoạt động tốt và tôi có thể thực thi các tập lệnh ruby ​​của mình als cronjob.

Alex Chamberlain đã giúp tôi rất nhiều và cho tôi những gợi ý quan trọng nhất. Cảm ơn rất nhiều vì sự giúp đỡ !!!

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.