Cách khắc phục tất cả các vấn đề / tai nạn liên quan đến crontab của bạn (Linux)
Đây là một wiki cộng đồng , nếu bạn nhận thấy bất cứ điều gì không đúng với câu trả lời này hoặc có thêm thông tin thì hãy chỉnh sửa nó.
Đầu tiên, thuật ngữ cơ bản:
- cron (8) là daemon thực thi các lệnh theo lịch trình.
- crontab (1) là chương trình được sử dụng để sửa đổi tập tin người dùng crontab (5).
- crontab (5) là một tệp cho mỗi người dùng có chứa các hướng dẫn cho cron (8).
Tiếp theo, giáo dục về cron:
Mỗi người dùng trên một hệ thống có thể có tệp crontab của riêng họ. Vị trí của tập tin crontab gốc và người dùng phụ thuộc vào hệ thống nhưng chúng thường nằm bên dưới /var/spool/cron
.
Có một /etc/crontab
tệp toàn hệ thống , /etc/cron.d
thư mục có thể chứa các đoạn crontab cũng được đọc và hành động bởi cron. Một số bản phân phối Linux (ví dụ: Red Hat) cũng có /etc/cron.{hourly,daily,weekly,monthly}
các thư mục, tập lệnh bên trong sẽ được thực thi mỗi giờ / ngày / tuần / tháng, với đặc quyền gốc.
root luôn có thể sử dụng lệnh crontab; người dùng thường xuyên có thể hoặc không thể được cấp quyền truy cập. Khi bạn chỉnh sửa tệp crontab bằng lệnh crontab -e
và lưu nó, crond sẽ kiểm tra tính hợp lệ cơ bản nhưng không đảm bảo tệp crontab của bạn được định dạng chính xác. Có một tệp được gọi cron.deny
sẽ chỉ định người dùng nào không thể sử dụng cron. Vị cron.deny
trí tệp phụ thuộc vào hệ thống và có thể bị xóa, điều này sẽ cho phép tất cả người dùng sử dụng cron.
Nếu máy tính không được bật hoặc crond daemon không chạy và ngày / giờ cho lệnh chạy đã trôi qua, crond sẽ không bắt kịp và chạy các truy vấn trong quá khứ.
crontab cụ thể, làm thế nào để xây dựng một lệnh:
Một lệnh crontab được đại diện bởi một dòng duy nhất. Bạn không thể sử dụng \
để mở rộng một lệnh trên nhiều dòng. Dấu băm ( #
) đại diện cho một nhận xét có nghĩa là bất cứ điều gì trên dòng đó bị bỏ qua bởi cron. Khoảng trắng hàng đầu và dòng trống được bỏ qua.
Hãy cẩn thận khi sử dụng dấu phần trăm ( %
) trong lệnh của bạn. Trừ khi chúng được thoát, \%
chúng được chuyển thành dòng mới và mọi thứ sau khi không thoát đầu tiên %
được chuyển đến lệnh của bạn trên stdin.
Có hai định dạng cho tệp crontab:
Người dùng crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
Hệ thống rộng /etc/crontab
và /etc/cron.d
mảnh
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * user-name command to be executed
Lưu ý rằng cái sau yêu cầu một tên người dùng. Lệnh sẽ được chạy như người dùng được đặt tên.
5 trường đầu tiên của dòng biểu thị thời gian khi lệnh sẽ được chạy. Bạn có thể sử dụng số hoặc nơi áp dụng tên ngày / tháng trong thông số thời gian.
- Các trường được phân cách bằng dấu cách hoặc tab.
- Dấu phẩy (
,
) được sử dụng để chỉ định danh sách, ví dụ 1,4,6,8, có nghĩa là chạy ở 1,4,6,8.
- Phạm vi được chỉ định bằng dấu gạch ngang (
-
) và có thể được kết hợp với các danh sách, ví dụ 1-3,9-12, có nghĩa là từ 1 đến 3 sau đó từ 9 đến 12.
- Ký
/
tự có thể được sử dụng để giới thiệu một bước, ví dụ 2/5, có nghĩa là bắt đầu từ 2 sau đó cứ sau 5 (2,7,12,17,22 ...). Họ không kết thúc quá khứ.
- Dấu hoa thị (
*
) trong trường biểu thị toàn bộ phạm vi cho trường đó (ví dụ: 0-59
trường phút).
- Phạm vi và các bước có thể được kết hợp, ví dụ:
*/2
biểu thị bắt đầu ở mức tối thiểu cho trường có liên quan sau đó cứ sau 2 ví dụ 0 trong vài phút (0,2 ... 58), 1 cho tháng (1,3 ... 11), v.v.
Gỡ lỗi lệnh cron
Kiểm tra thư!
Theo mặc định, cron sẽ gửi bất kỳ đầu ra nào từ lệnh tới người dùng, nó đang chạy lệnh dưới dạng. Nếu không có đầu ra sẽ không có thư. Nếu bạn muốn cron gửi thư đến một tài khoản khác thì bạn có thể đặt biến môi trường MAILTO trong tệp crontab, vd
MAILTO=user@somehost.tld
1 2 * * * /path/to/your/command
Tự mình nắm bắt đầu ra
Bạn có thể chuyển hướng thiết bị xuất chuẩn và thiết bị xuất chuẩn vào một tệp. Cú pháp chính xác để chụp đầu ra có thể thay đổi tùy thuộc vào việc sử dụng cron shell nào. Dưới đây là hai ví dụ lưu tất cả đầu ra vào một tệp tại /tmp/mycommand.log
:
1 2 * * * /path/to/your/command &>/tmp/mycommand.log
1 2 * * * /path/to/your/command >/tmp/mycommand.log 2>&1
Nhìn vào nhật ký
Cron ghi lại các hành động của nó thông qua syslog, mà (tùy thuộc vào thiết lập của bạn) thường đi đến /var/log/cron
hoặc /var/log/syslog
.
Nếu được yêu cầu, bạn có thể lọc các câu lệnh cron với vd
grep CRON /var/log/syslog
Bây giờ chúng ta đã tìm hiểu những điều cơ bản về cron, nơi chứa các tệp và cách sử dụng chúng, hãy xem xét một số vấn đề phổ biến.
Kiểm tra xem cron có đang chạy không
Nếu cron không chạy thì các lệnh của bạn sẽ không được lên lịch ...
ps -ef | grep cron | grep -v grep
sẽ giúp bạn một cái gì đó như
root 1224 1 0 Nov16 ? 00:00:03 cron
hoặc là
root 2018 1 0 Nov14 ? 00:00:06 crond
Nếu không khởi động lại nó
/sbin/service cron start
hoặc là
/sbin/service crond start
Có thể có các phương pháp khác; sử dụng những gì distro của bạn cung cấp.
cron chạy lệnh của bạn trong một môi trường hạn chế.
Những biến môi trường có sẵn có khả năng rất hạn chế. Thông thường, bạn sẽ chỉ nhận được một vài biến xác định, chẳng hạn như $LOGNAME
, $HOME
, và $PATH
.
Đặc biệt lưu ý PATH
là hạn chế /bin:/usr/bin
. Phần lớn các sự cố "tập lệnh cron của tôi không hoạt động" là do đường dẫn hạn chế này gây ra . Nếu lệnh của bạn ở một vị trí khác, bạn có thể giải quyết điều này theo một số cách:
Cung cấp đường dẫn đầy đủ đến lệnh của bạn.
1 2 * * * /path/to/your/command
Cung cấp một PATH phù hợp trong tệp crontab
PATH=/usr:/usr/bin:/path/to/something/else
1 2 * * * command
Nếu lệnh của bạn yêu cầu các biến môi trường khác, bạn cũng có thể xác định chúng trong tệp crontab.
cron chạy lệnh của bạn với cwd == $ HOME
Bất kể chương trình bạn thực hiện nằm ở đâu trên hệ thống tập tin, thư mục làm việc hiện tại của chương trình khi cron chạy, nó sẽ là thư mục chính của người dùng . Nếu bạn truy cập các tệp trong chương trình của mình, bạn sẽ cần tính đến điều này nếu bạn sử dụng các đường dẫn tương đối hoặc (tốt nhất là) chỉ sử dụng các đường dẫn đủ điều kiện ở mọi nơi và tiết kiệm cho mọi người rất nhiều sự nhầm lẫn.
Lệnh cuối cùng trong crontab của tôi không chạy
Cron thường yêu cầu các lệnh được kết thúc bằng một dòng mới. Chỉnh sửa crontab của bạn; đi đến cuối dòng chứa lệnh cuối cùng và chèn một dòng mới (nhấn enter).
Kiểm tra định dạng crontab
Bạn không thể sử dụng crontab được định dạng crontab cho / etc / crontab hoặc các đoạn trong /etc/cron.d và ngược lại. Một crontab được định dạng người dùng không bao gồm tên người dùng ở vị trí thứ 6 của hàng, trong khi một crontab được định dạng hệ thống bao gồm tên người dùng và chạy lệnh như người dùng đó.
Tôi đặt một tệp trong /etc/cron. Đũahourly, hàng ngày, hàng tháng, hàng tháng} và nó không chạy
- Kiểm tra xem tên tệp không có phần mở rộng xem phần chạy
- Đảm bảo tệp có quyền thực thi.
- Nói cho hệ thống biết nên sử dụng gì khi thực thi tập lệnh của bạn (ví dụ: đặt
#!/bin/sh
ở trên cùng)
Cron ngày liên quan đến lỗi
Nếu ngày của bạn gần đây bị thay đổi bởi người dùng hoặc cập nhật hệ thống, múi giờ hoặc khác, thì crontab sẽ bắt đầu hành xử thất thường và biểu hiện các lỗi kỳ quái, đôi khi không hoạt động, đôi khi không. Đây là nỗ lực của crontab để cố gắng "làm những gì bạn muốn" khi thời gian thay đổi từ bên dưới nó. Trường "phút" sẽ trở nên không hiệu quả sau khi giờ được thay đổi. Trong kịch bản này, chỉ các dấu sao sẽ được chấp nhận. Khởi động lại cron và thử lại mà không cần kết nối với internet (vì vậy ngày không có cơ hội đặt lại vào một trong các máy chủ thời gian).
Dấu hiệu phần trăm, một lần nữa
Để nhấn mạnh lời khuyên về các dấu hiệu phần trăm, đây là một ví dụ về những gì cron làm với chúng:
# cron entry
* * * * * cat >$HOME/cron.out%foo%bar%baz
sẽ tạo tệp ~ / cron.out chứa 3 dòng
foo
bar
baz
Điều này đặc biệt xâm phạm khi sử dụng date
lệnh. Hãy chắc chắn để thoát khỏi các dấu hiệu phần trăm
* * * * * /path/to/command --day "$(date "+\%Y\%m\%d")"