Câu hỏi Tại sao script crontab không hoạt động?


Thông thường, crontab các tập lệnh không được thực hiện đúng tiến độ hoặc theo dự kiến. Có nhiều lý do cho điều đó:

  1. ký hiệu crontab sai
  2. vấn đề quyền
  3. biến môi trường

Wiki cộng đồng này nhằm tổng hợp các lý do hàng đầu cho crontab các tập lệnh không được thực hiện như mong đợi. Viết từng lý do vào một câu trả lời riêng.

Vui lòng bao gồm một lý do cho mỗi câu trả lời - chi tiết về lý do tại sao nó không được thực hiện - và sửa (es) cho một lý do đó.

Vui lòng chỉ viết các vấn đề cụ thể về cron, ví dụ: lệnh thực hiện như mong đợi từ trình bao nhưng thực thi sai bởi cron.


455


gốc


Bạn phải đóng crontab -e để cron có tác dụng. Ví dụ sử dụng vim tôi chỉnh sửa tập tin và sử dụng :w để viết nó nhưng công việc không được thêm vào cron cho đến khi tôi bỏ thuốc lá nữa. Vì vậy, tôi sẽ không thấy công việc cho đến sau khi tôi :q cũng thế. - DutGRIFF
Tôi nghĩ cách tốt nhất để gỡ lỗi cron là kiểm tra nhật ký hệ thống và tìm ra vấn đề. - Suneel Kumar
Trong trường hợp của tôi - email đã đến thư mục SPAM của tôi, vì vậy ..... kiểm tra xem trước khi bạn bỏ ra hàng giờ để gỡ lỗi: D - almaruf
Cúp điện - Josef Klimuk


Các câu trả lời:


Môi trường khác

Cron chuyển một bộ biến môi trường tối thiểu cho công việc của bạn. Để thấy sự khác biệt, hãy thêm một công việc giả như thế này:

* * * * * env> /tmp/env.output

Chờ /tmp/env.output được tạo, sau đó xóa công việc một lần nữa. Bây giờ so sánh nội dung của /tmp/env.output với đầu ra của env chạy trong thiết bị đầu cuối thông thường của bạn.

Một "hình ảnh" phổ biến ở đây là PATH biến môi trường khác nhau. Có lẽ kịch bản cron của bạn sử dụng lệnh somecommand tìm thấy trong /opt/someApp/binmà bạn đã thêm vào PATH trong /etc/environment? cron bỏ qua PATH từ tệp đó, do đó, runnning somecommand từ tập lệnh của bạn sẽ thất bại khi chạy với cron, nhưng hoạt động khi chạy trong một thiết bị đầu cuối. Cần lưu ý rằng các biến từ /etc/environment sẽ được chuyển sang các công việc cron, không phải các biến cron cụ thể đặt, chẳng hạn như PATH.

Để giải quyết vấn đề đó, chỉ cần thiết lập PATH biến ở đầu tập lệnh. Ví dụ.

#!/bin/bash
PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# rest of script follows

Một số thích chỉ sử dụng đường dẫn tuyệt đối cho tất cả các lệnh thay thế. Tôi khuyên bạn nên chống lại điều đó. Hãy xem xét điều gì sẽ xảy ra nếu bạn muốn chạy tập lệnh của mình trên một hệ thống khác và trên hệ thống đó, lệnh này nằm trong /opt/someAppv2.2/bin thay thế. Bạn sẽ phải trải qua toàn bộ kịch bản thay thế /opt/someApp/bin với /opt/someAppv2.2/bin thay vì chỉ thực hiện một chỉnh sửa nhỏ trên dòng đầu tiên của tập lệnh.

Bạn cũng có thể đặt biến PATH trong tệp crontab, nó sẽ áp dụng cho tất cả các công việc cron. Ví dụ.

PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

15 1 * * * backupscript --incremental /home /root

431



Tôi nghĩ rằng tôi chỉ rơi cho điều này, và dòng mới ở cuối ... đôi whammy. - WernerCD
+1 cho env, Tôi đã hoàn toàn quên mất mệnh lệnh đó và nghĩ rằng PATH đang làm việc. Nó thực sự khác biệt trong trường hợp của tôi. - Izkata
@pbr Nếu các thư mục này có thể ghi được cho người khác, hệ thống đã bị xâm phạm. - geirha
@pbr Một sysadmin có thể vô tình xóa hệ thống tập tin gốc. Bạn không thể bảo vệ chống lại sysadmins sai lầm ngớ ngẩn. Nếu bạn cài đặt phiên bản mới hơn của trình thông dịch không tương thích ngược, tôi mong đợi vỡ bất kể. Cách lành mạnh để xử lý đó là cài đặt nó như một lệnh khác. Ví dụ. bạn có phiên bản python 2.x và cài đặt python 3, bạn cài đặt nó như python3, không phải python. Và đối với / opt / someApp / bin, tại sao trên trái đất nó sẽ không có quyền sane / quyền sở hữu? bất kỳ quản trị viên sane nào cũng sẽ đảm bảo quyền / quyền sở hữu lành mạnh trên các tệp hệ thống. - geirha
@pbr Có vẻ như chúng ta có thể tiếp tục mãi mãi, vâng. Tôi vẫn không thấy lý do tại sao nó là một ý tưởng tồi để sử dụng PATH mặc dù. Nếu bạn muốn thảo luận thêm về điều này trong một môi trường phù hợp hơn để thảo luận, bạn sẽ tìm thấy tôi trong #ubuntu và #bash, trong số các kênh khác, trên irc.freenode.net - geirha


Lưu ý hàng đầu của tôi: Nếu bạn quên thêm dòng mới vào cuối crontab tập tin. Nói cách khác, tệp crontab sẽ kết thúc bằng một dòng trống.

Dưới đây là phần có liên quan trong các trang hướng dẫn cho vấn đề này (man crontab sau đó bỏ qua đến cuối):

   Although cron requires that each entry in a crontab end  in  a  newline
   character,  neither the crontab command nor the cron daemon will detect
   this error. Instead, the crontab will appear to load normally. However,
   the  command  will  never  run.  The best choice is to ensure that your
   crontab has a blank line at the end.

   4th Berkeley Distribution      29 December 1993               CRONTAB(1)

291



đây là một showstopper như vậy, làm thế nào đến nó đã không được cố định trong nhiều năm của cron? - Capi Etheriel
Dường như được cố định trong Vixie cron: man crontab trên Ubuntu 10.10 nói "cron yêu cầu mỗi mục nhập trong một đầu crontab trong một ký tự dòng mới. Nếu mục nhập cuối cùng trong một crontab bị thiếu dòng mới, cron sẽ xem xét crontab (ít nhất một phần) bị hỏng và từ chối cài đặt nó." (Và ngày cuối cùng là ngày 19 tháng 4 năm 2010.) - Marius Gedminas
@barraponto Đây thực sự là một lỗi trong trình chỉnh sửa văn bản mới. Ký tự "newline" được cho là một chấm dứt dòng ký tự, do đó, dòng cuối cùng trong một tệp văn bản được cho là kết thúc bằng một ký tự dòng mới không được hiển thị trong trình chỉnh sửa. Vi và vim sử dụng các ký tự một cách chính xác, và cron được xây dựng trước khi các biên tập viên mới bắt đầu hành vi kỳ lạ của họ ... Do đó chơi nó lưu và bao gồm một dòng trống. - Izkata
Nếu bạn chỉnh sửa crontab bằng cách sử dụng crontab -e nó sẽ kiểm tra cú pháp của tập tin trước khi cho phép lưu, bao gồm cả một kiểm tra cho dòng mới. - Tom Harrison Jr
@ Chan-HoSuh, theo trang người đàn ông "cron yêu cầu mỗi mục trong một đầu crontab trong một ký tự newline. Nếu mục nhập cuối cùng trong một crontab là thiếu newline, cron sẽ xem xét các crontab (ít nhất một phần) bị hỏng và từ chối cài đặt nó." Hành vi này sẽ được gọi khi chỉnh sửa rồi lưu crontab bằng cách sử dụng -e tùy chọn và độc lập với trình chỉnh sửa. - Tom Harrison Jr


Cron daemon không hoạt động. Tôi thực sự say mê với điều này một vài tháng trước đây.

Kiểu:

pgrep cron 

Nếu bạn thấy không có số thì cron sẽ không chạy. sudo /etc/init.d/cron start có thể được sử dụng để khởi động cron.

EDIT: Thay vì gọi init script thông qua /etc/init.d, hãy sử dụng dịch vụ tiện ích, ví dụ:

sudo service cron start

125



Cảm ơn bạn đã cho tôi xem pgrep. Tôi tiếp tục làm ps -ef | grep foo - ripper234
Bạn cũng có thể sử dụng pidof cron sẽ bỏ qua kết quả cho các ứng dụng khác cũng có từ 'cron', như crontab. - Pithikos
Lạ lùng, tất cả những điều này cho tôi thấy không có gì để hiển thị cron đang chạy, nhưng nếu tôi chạy sudo service cron start tôi có start: Job is already running: cron - Colleen
service crond start nếu centos / RHEL của nó - Srihari Karanth


Tên tệp kịch bản trong cron.d/, cron.daily/, cron.hourly/, v.v., không được chứa dấu chấm (.), nếu không thì các phần chạy sẽ bỏ qua chúng.

Xem phần chạy (8):

   If neither the --lsbsysinit option nor the --regex option is given then
   the names must consist entirely of upper and lower case  letters,  dig‐
   its, underscores, and hyphens.

   If  the  --lsbsysinit  option  is given, then the names must not end in
   .dpkg-old  or .dpkg-dist or .dpkg-new or .dpkg-tmp, and must belong  to
   one  or more of the following namespaces: the LANANA-assigned namespace
   (^[a-z0-9]+$);   the   LSB   hierarchical   and   reserved   namespaces
   (^_?([a-z0-9_.]+-)+[a-z0-9]+$);  and  the  Debian cron script namespace
   (^[a-zA-Z0-9_-]+$).

Vì vậy, nếu bạn có một kịch bản cron backup.sh, analyze-logs.pl trong cron.daily/ thư mục, bạn nên xóa tên tiện ích.


83



Đó là một tính năng không phải là lỗi - nó giữ những thứ như myscript.backup hoặc myscript.original hoặc myscript.rpm-new chạy ngay bên cạnh myscript. - pbr
@pbr: có ý nghĩa. Ít nhất nó sẽ hữu ích cho việc gỡ lỗi nếu run-parts --test (hoặc một tùy chọn tưởng tượng khác như --debug sẽ xuất ra các tệp mà nó bỏ qua bao gồm cả lý do. - Rabarberski
Nếu đây là một tính năng, nó không phải là một tính năng tốt đẹp: (Rất nhiều người sử dụng dấu chấm trong tên tập tin (backup.sh là một trong những phổ biến nhất) .Nếu bạn muốn một kịch bản để ngừng thực hiện, phương pháp hợp lý nhất sẽ là xóa nó khỏi thư mục "cron.d". - MatuDuke
Đây là một tính năng tồi tệ đến nỗi nó thực sự là một lỗi. Đó là thực tế phổ biến để yêu cầu một kết thúc cụ thể (như ".list" hoặc ".cron" hoặc một cái gì đó) nếu mọi người muốn đảm bảo rằng mọi thứ chỉ chạy khi dự định. Tự ý chọn dấu chấm làm dấu phân cách có khả năng cho ".bak" hoặc ".temp" hoặc bất kỳ thứ gì, hoàn toàn không thể đoán trước ngoại trừ cách nó có thể làm người khác nhầm lẫn. Các kết thúc hợp pháp như ".sh" và ".pl" đã được sử dụng rộng rãi trong nhiều thập kỷ. Rất nhiều người sử dụng "_bak" hoặc "_temp" hoặc "-bak" thay vì dấu chấm, tuy nhiên. Đây là một lựa chọn thiết kế khủng khiếp; đó là một lỗi thiết kế tốt nhất. - Teekin


Trong nhiều môi trường, cron thực thi các lệnh bằng sh, trong khi nhiều người cho rằng nó sẽ sử dụng bash.

Gợi ý để kiểm tra hoặc sửa lỗi này cho lệnh không thành công:

  • Thử chạy lệnh trong sh để xem nó có hoạt động không
  • Quấn lệnh trong bash subshell để chắc chắn rằng nó được chạy trong bash:
    bash -c "mybashcommand"
  • Yêu cầu cron chạy tất cả các lệnh trong bash bằng cách đặt shell ở đầu crontab của bạn:
    SHELL=/bin/bash
  • Nếu lệnh là một tập lệnh, hãy đảm bảo tập lệnh có chứa một shebang:
    #!/bin/bash

55



bash gợi ý là rất hữu ích, vấn đề cố định với cron của tôi. - Maxim Galushka
Điều này chỉ gây ra cho tôi 1 giờ không quan trọng / xử lý sự cố. Thậm chí còn phức tạp hơn nếu bạn không biết vấn đề là kịch bản sẽ chạy thủ công tốt nếu bạn là shell điển hình bash, nhưng không phải với cron. Cảm ơn! - Hendy
Một thời gian dài trước đây tôi đã gặp phải điều gì đó liên quan: Lệnh source là bash nhưng không sh. Trong cron / sh, sử dụng một khoảng thời gian: . envfile thay vì source envfile. - kungphu


Tôi đã có một số vấn đề với các múi giờ. Cron đang chạy với múi giờ cài đặt mới. Giải pháp là khởi động lại cron:

sudo service cron restart

34



Có, sau khi thay đổi múi giờ trên một hệ thống, người ta phải khởi động lại mọi dịch vụ quan tâm đến thời gian đó, hoặc khởi động lại. Tôi thích khởi động lại, để chắc chắn rằng tôi đã bắt được mọi thứ. - pbr
Ôi vì Chúa, giờ đã giết ngày này. Đã thử khởi động lại dịch vụ sau * * * * * touch /tmp/cronworks không làm gì, nhưng có RELOAD tại cronlog. - НЛО


Nếu lệnh crontab của bạn có % biểu tượng trong đó, cron cố gắng diễn giải nó. Vì vậy, nếu bạn đang sử dụng bất kỳ lệnh nào với % trong đó (chẳng hạn như một đặc tả định dạng cho lệnh date), bạn sẽ cần phải thoát khỏi nó.

Điều đó và gotchas tốt khác ở đây:
http://www.pantz.org/software/cron/croninfo.html


29



Đây là những gì đã khiến công việc Cron của tôi thất bại trong tuần qua. Cuối cùng đã tìm ra rằng Ngày của tôi không có một ký tự thoát (dấu gạch chéo ngược cho bất kỳ người nào khác tìm kiếm ký tự thoát là gì). Yay! - Valien
Xem thêm Làm thế nào tôi có thể thực thi date bên trong của một công việc tab cron? - Jared Beck
Điều này một chút tôi là tốt. Cảm ơn! - stefansundin


Đường dẫn tuyệt đối nên được sử dụng cho tập lệnh:

Ví dụ, /bin/grep nên được sử dụng thay vì grep:

# m h  dom mon dow   command
0 0 *  *  *  /bin/grep ERROR /home/adam/run.log &> /tmp/errors

Thay vì:

# m h  dom mon dow   command
0 0 *  *  *  grep ERROR /home/adam/run.log &> /tmp/errors

Điều này đặc biệt phức tạp, bởi vì cùng một lệnh sẽ hoạt động khi được thực thi từ trình bao. Lý do là cron không có cùng PATH biến môi trường như người dùng.


28



xem geirha câu trả lời, bạn có thể (phải) xác định Cron's PATH - Capi Etheriel
Bzzt. bạn KHÔNG cần định nghĩa PATH - sử dụng đường dẫn tuyệt đối là thực hành tốt nhất ở đây. "bởi vì một tập tin thực thi có thể ở đâu đó trên một số máy tính khác" không có chủ đề "Tôi muốn nó chạy chính xác chương trình này và không phải một số người khác đặt vào đường dẫn trước chương trình gốc của tôi" - pbr
yep đây là nó cho tôi, bên ngoài cron tôi có thể chạy lệnh trực tiếp, bên trong cron nó cần đầy đủ /usr/bin/whatever con đường - Anentropic


Cũng có thể mật khẩu của người dùng đã hết hạn. Ngay cả mật khẩu của root cũng có thể hết hạn. Bạn có thể tail -f /var/log/cron.log và bạn sẽ thấy cron thất bại với mật khẩu hết hạn. Bạn có thể đặt mật khẩu để không bao giờ hết hạn bằng cách thực hiện việc này: passwd -x -1 <username>

Trong một số hệ thống (Debian, Ubuntu), ghi nhật ký cho cron không được kích hoạt theo mặc định. Trong /etc/rsyslog.conf hoặc là /etc/rsyslog.d/50-default.conf dòng:

# cron.*                          /var/log/cron.log

nên được chỉnh sửa (sudo nano /etc/rsyslog.conf) không được chú ý đến:

cron.*                          /var/log/cron.log

Sau đó, bạn cần phải khởi động lại rsyslog thông qua

/etc/init.d/rsyslog restart

hoặc là

service rsyslog restart 

Nguồn: Bật ghi nhật ký crontab trong Debian Linux

Trong một số hệ thống (Ubuntu) tập tin ghi nhật ký riêng biệt cho cron không được kích hoạt theo mặc định, nhưng cron liên quan đến các bản ghi đang xuất hiện trong tập tin syslog. Người ta có thể sử dụng

cat /var/log/syslog | grep cron

để xem các tin nhắn liên quan đến cron.


23



Tôi có Debian (wheezy) nhưng không có /etc/init.d/rsyslog, chỉ inetutils-syslogd và sysklogd. Tôi có phải cài đặt một cái gì đó hoặc chỉ cần khởi động lại một trong hai? - hgoebl


Cron đang gọi một tập lệnh không thực thi được.

Bằng cách chạy chmod +x /path/to/scrip tập lệnh trở nên thực thi và nên giải quyết vấn đề này.


21



Đó không phải là duy nhất cronvà dễ dàng theo dõi bằng cách chỉ cần thực hiện /path/to/script từ dòng lệnh. - Adam Matan
Nếu bạn đang sử dụng để thực thi các tập lệnh với . scriptname hoặc là sh scriptname hoặc là bash scriptname, sau đó điều này sẽ trở thành cronvấn đề cụ thể. - Eliah Kagan


Nếu cronjob của bạn gọi các ứng dụng GUI, bạn cần phải cho họ biết họ nên sử dụng DISPLAY nào.

Ví dụ: Firefox khởi động với cron.

Tập lệnh của bạn nên chứa export DISPLAY=:0 một vài nơi.


16



aplay cần cái này vì lý do nào đó. cảm ơn bạn - IljaBek
* * * * * export DISPLAY=:0 && <command> - LoMaPh