Làm thế nào tôi có thể lập trình tạo một công việc định kỳ mới?


129

Tôi muốn có thể lập trình thêm một công việc định kỳ mới, cách tốt nhất để làm điều này là gì?

Từ nghiên cứu của tôi , có vẻ như tôi có thể đổ crontab hiện tại và sau đó nối thêm một cái mới, đưa nó trở lại crontab:

(crontab -l ; echo "0 * * * * wget -O - -q http://www.example.com/cron.php") | crontab -

Có cách nào tốt hơn?


2
Giải pháp của bạn có vẻ như là một tốt.
Craig S

Trên Solaris chỉ cần loại bỏ dấu gạch ngang cho crontab cuối cùng. Bạn có thể thêm một grep để tránh thêm một dòng đã có.
lacroix1547


niềng răng xoăn thay vì dấu ngoặc đơn sẽ làm điều đó mà không sinh ra một quá trình. Đảm bảo giữ khoảng trống xung quanh dấu ngoặc nhọn, {...; }.
Jay Winston

Câu trả lời:


-25

Nó luôn hoạt động tốt với tôi.

Bạn nên xem xét một kịch bản phức tạp hơn một chút có thể làm ba việc.

  1. Nối một dòng crontab; đảm bảo rằng nó không tồn tại. Thêm khi nó đã tồn tại là xấu.

  2. Loại bỏ dòng crontab. Có lẽ chỉ cảnh báo nếu nó không tồn tại.

  3. Một sự kết hợp của hai tính năng trên để thay thế dòng crontab.


78
Anh hỏi làm sao và em bảo anh cái gì?
Cerin

1
Nếu người dùng chưa có crontab thì sao?
Maxim Egorushkin

132

Cách tốt nhất nếu bạn đang chạy với quyền root, là thả tệp vào /etc/cron.d

nếu bạn sử dụng trình quản lý gói để đóng gói phần mềm của mình, bạn chỉ cần đặt các tệp trong thư mục đó và chúng được hiểu như thể chúng là crontabs, nhưng có thêm một trường cho tên người dùng, ví dụ:

Tên tệp: /etc/cron.d/per_minute

Nội dung: * * * * * root /bin/sh /home/root/script.sh


5
Chỉ cần đảm bảo phiên bản của cron đang sử dụng hỗ trợ /etc/cron.d/. Hầu hết các bản phân phối Linux hiện đại đều có.
sleske

8
Đây là giải pháp đơn giản nhất, thanh lịch nhất. Nhịp đập chắc chắn phải phân tích và chỉnh sửa một crontab hiện có với các mục không liên quan khác.
Cerin

13
Một cảnh báo tiềm năng cho điều này là tần suất mà cron chọn các bổ sung mới cho thư mục này (một lần mỗi giờ). Nếu bạn đang mong đợi công việc của mình bắt đầu chạy ngay lập tức, hãy cẩn thận.
JonathanK

6
@JonathanK, bạn có biết cron có thể được yêu cầu quét lại /etc/cron.d/*không? Thật khó để biết nếu một cái gì đó đang hoạt động nếu người ta phải chờ một giờ để kiểm tra!
giảm tốc

4
Làm thế nào perms thiết lập cho tập tin này? chmod + x /etc/cron.d/per_minute?
giò

101

Giải pháp của OP có một lỗi, nó có thể cho phép các mục được thêm hai lần, sử dụng bên dưới để khắc phục.

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -

5
Đây thực sự là một giải pháp tốt hơn nếu không được mô tả. Nó đảm bảo lệnh không được thêm hai lần vào crontab.
Bufke

2
Đây không phải là một sửa chữa tốt cho vấn đề nhập trùng lặp. Điều gì xảy ra nếu một dòng khác được thêm vào crontab trong khi đó?
hmn

6
Để đảm bảo tính duy nhất, ngay sorttrước đó uniq, ví dụ:(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
mway 21/03 '

6
Không cần uniq. Sử dụng -utùy chọn trên sort.
papiro

6
Làm thế nào để tránh không có crontab cho người dùng khi tôi chỉnh sửa crontab lần đầu tiên.
wyx

23

Để thêm một cái gì đó vào cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | sort | uniq | crontab -

Để loại bỏ điều này khỏi cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | grep -v hupChannel.sh |  sort | uniq | crontab -

hy vọng sẽ giúp được ai đó


Đây chính xác là những gì tôi đang tìm kiếm tôi sẽ chỉ cần thêm điều này: | grep -v '^ #' | để lọc ra các bình luận
Tjunkie

2
Bạn thực sự không cần 2>&1 | grep -v "no crontab"vì khi không có crontab, dòng đầu ra crontab: no crontab for...được gửi đến stderr. Không có lý do để nắm bắt đầu ra đó, gửi nó đến thiết bị xuất chuẩn, và sau đó lọc nó ra bằng grep. Nếu mục tiêu của bạn là để tránh nhìn thấy crontab: no crontab for...trong đầu ra của bạn, sau đó sử dụng 2> /dev/null | sort.....
matty

6

Nếu bạn đang dự định thực hiện nó cho một kịch bản chạy một lần chỉ để quên một cái gì đó, hãy xem 'tại'


6

Chỉ cần thay đổi trình chỉnh sửa thành lệnh tee:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e

3
Cẩn thận - điều này xóa sạch mọi mục hiện có.
starfry

5

Giả sử rằng đã có một mục trong crontab của bạn, lệnh sau sẽ hoạt động tương đối tốt. Lưu ý rằng $CMDbiến chỉ có ở đó để dễ đọc. Sắp xếp trước khi lọc trùng lặp là rất quan trọng, bởi vì uniqchỉ hoạt động trên các dòng liền kề.

CMD='wget -O - -q http://www.example.com/cron.php"'
(crontab -l ; echo "0 * * * * $CMD") | sort | uniq | crontab -

Nếu bạn hiện có một crontab trống, bạn sẽ nhận được lỗi sau đối với stderr:

no crontab for user

Nếu bạn muốn tránh điều này, bạn có thể thêm một chút phức tạp thêm làm một cái gì đó như thế này:

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -

5

Hầu hết các giải pháp ở đây là để thêm dòng vào crontab. Nếu bạn cần kiểm soát nhiều hơn, bạn sẽ muốn có thể kiểm soát toàn bộ nội dung của crontab.

Bạn có thể sử dụng đường ống để làm điều này khá thanh lịch.

Để viết lại hoàn toàn crontab, hãy làm

echo "2 2 2 2 2 /bin/echo foobar" |crontab -

Điều này nên dễ dàng kết hợp với các câu trả lời khác được mô tả ở đây như

crontab -l | <something> | tee |crontab -

Hoặc, nếu bạn có nội dung trong một tệp, nó thậm chí còn đơn giản hơn

cat <file> |crontab -

3

Đây là một cách khác, tránh trùng lặp

(crontab -l 2>/dev/null | fgrep -v "*/1 *  *  *  * your_command"; echo "*/1 *  *  *  * your_command") | crontab -

Và đây là một cách để thực hiện câu trả lời của JohnZ và tránh no crontab for usertin nhắn, hoặc nếu bạn cần phải hoạt động trong một set -eumôi trường loại và không thể có bất cứ điều gì trả lại thất bại (trong trường hợp đó là 2>/dev/nullphần tùy chọn):

( (crontab -l 2>/dev/null || echo "")  ; echo "0 * * * * your_command") | sort -u - | crontab -

Hoặc nếu bạn muốn chia nhỏ mọi thứ để chúng dễ đọc hơn:

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
(echo "$preceding_cron_jobs" ; echo "$new_job") | sort - | uniq - | crontab -

Hoặc tùy ý xóa mọi tham chiếu đến your_command (ví dụ: nếu lịch biểu đã thay đổi, bạn chỉ muốn nó được ghi lại một lần). Trong trường hợp này, chúng tôi không còn cần uniq(thêm tiền thưởng, thứ tự chèn cũng được giữ nguyên):

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
preceding_cron_jobs=$(echo "$preceding_cron_jobs" | grep -v your_command )
(echo "$preceding_cron_jobs" ; echo "$new_job") | crontab -

2

người đàn ông crontab cũng hữu ích:

CRONTAB (1)

TÊN

   crontab - manipulate per-user crontabs (Dillon's Cron)

TÓM TẮC

   crontab file [-u user] - replace crontab from file

   crontab - [-u user] - replace crontab from stdin

   crontab -l [user] - list crontab for user

3
Phần nói "thay thế crontab từ stdin" thực sự là một nửa câu trả lời :-)
Grodriguez

2

Thêm vào câu trả lời của JohnZ, đây là cú pháp để lên lịch làm root nếu bạn là người sudoer:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -

1
function cronjob_exists($command){

    $cronjob_exists=false;

    exec('crontab -l', $crontab);


    if(isset($crontab)&&is_array($crontab)){

        $crontab = array_flip($crontab);

        if(isset($crontab[$command])){

            $cronjob_exists=true;

        }

    }
    return $cronjob_exists;
}

function append_cronjob($command){

    if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){

        //add job to crontab
        exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);


    }

    return $output;
}

    append_cronjob('* * * * * curl -s http://localhost/cron/test.php');

1

Điều này sẽ kiểm tra để đảm bảo rằng lệnh của bạn không tồn tại trước khi thêm nó.

crontab -l 2>/dev/null | grep -q '/path/to/script' || echo "5 * * * * /path/to/script" | crontab -

Chúc mừng.


0

Thiết bị xuất chuẩn crontabkhông cài đặt crontab mới cho tôi trên macOS, vì vậy tôi đã tìm giải pháp này thay vào đó, bằng cách sử dụng teetrình chỉnh sửa trong trình bao phụ:

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)

0

Nếu bạn muốn tác vụ chạy như một người dùng:

crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | crontab -

Nếu bạn muốn tác vụ chạy với đặc quyền:

sudo crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | sudo crontab -

và kiểm tra tác vụ (có hoặc không có 'sudo'):

crontab -l | sed '/^$/d; /#/d'

-1

ngoài ra, bạn có thể thêm các tác vụ của mình vào /etc/cron.*/


-2

Bạn cũng có thể chỉnh sửa trực tiếp tệp văn bản bảng cron, nhưng giải pháp của bạn có vẻ hoàn toàn chấp nhận được.


1
Tôi sẽ không hài lòng về điều này do lo ngại về cơ hội chỉnh sửa đồng thời gây ra tham nhũng tệp. Sử dụng lệnh crontab dòng lệnh nên tránh vấn đề đó.
Craig S

Craig, không cần nghiên cứu thêm, tôi sẽ không chắc chắn rằng phiên bản dòng lệnh là nguyên tử và an toàn tình trạng chủng tộc. Có lẽ "khá an toàn".
tuomassalo

"Chỉnh sửa tệp trực tiếp" không khả thi nếu không có quyền truy cập root (miễn là bạn có thể tìm ra nơi tệp crontab của người dùng tồn tại và cách đảm bảo cron daemon nhận chính xác các thay đổi của bạn) và "chỉnh sửa" theo cách lập trình là câu hỏi muốn tư vấn về nơi đầu tiên.
tripleee
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.