หลังจากที่เพื่อน ๆ ได้เขียนโปรแกรมมาระยะนึง ก็อาจจะเกิดคำถามว่า “จะเป็นไปได้ไหมที่เราจะตั้งเวลา (schedule) ให้โปรแกรม Python ของเรานั้น ทำงานตามกำหนดเวลาโดยอัตโนมัติ” ตัวอย่างเช่น เราอาจจะเขียนโปรแกรมเพื่อดึงข้อมูลจาก API หรือทำการดึงข้อมูลจากเว็บไซต์ผ่านเทคนิค Web Scraping และต้องการที่จะตั้งเวลาให้ Python script ของเรานั้นดึงข้อมูลใหม่ทุก ๆ วัน

ในบทความนี้ เราจะพาเพื่อน ๆ ไปรู้จักและทดลองใช้ CRON เครื่องมือที่ช่วยให้เราสามารถตั้งเวลาทำงานของ Python script โดยอัตโนมัติบน Linux

สำหรับเพื่อน ๆ ที่สนใจการดึงข้อมูลจากเว็บไซต์ สามารถเข้าไปดูตัวอย่างได้จากลิงก์เหล่านี้นะคะ


CRON คืออะไร ?

  • Cron เป็นเครื่องมือบน Linux ที่ช่วยให้เราสามารถกำหนดเวลา การทำงานของ script หรือ คำสั่งต่าง ๆ ได้โดยอัตโนมัติ
  • โดยที่เราจะระบุ Cron job หรือ Cron schedule ซึ่งประกอบด้วยคำสั่งที่ต้องการกำหนดการทำงานควบคู่กับเวลาการทำงาน ภายในไฟล์ Crontab

“Cron มาจากภาษากรีก Chronos ซึ่งมีความหมายถึง เวลา”

“Crontab มาจาก Cron table จึงเปรียบเสมือน timetable หรือ ตารางเวลา”


การเขียนไฟล์ Crontab

รูปแบบกำหนดการ

การตั้งกำหนดการทำงานของคำสั่งต่าง ๆ ผ่าน Cron นั้นไม่ใช่เรื่องยาก เพียงแต่เราต้องเรียนรู้ รูปแบบการเขียนกำหนดการ ภายในไฟล์ Crontab

รูปแบบการเขียนกำหนดการภายในไฟล์ Crontab

ไฟล์ Crontab จะจัดเก็บกำหนดการทำงานของแต่ละคำสั่งไว้ในแต่ละบรรทัด โดยที่แต่ละบรรทัดจะประกอบไปด้วย fields ที่ระบุเวลาการทำงานของคำสั่งจำนวน 5 fields และตามด้วย คำสั่ง นั้น ๆ กล่าวคือ

Field ที่ 1ระบุ นาที (0 – 59) ที่คำสั่งจะทำงาน
Field ที่ 2ระบุ ชั่วโมง (0 – 23) ที่คำสั่งจะทำงาน
Field ที่ 3ระบุ วัน (1 – 31) ที่คำสั่งจะทำงาน
Field ที่ 4ระบุ เดือน (1 – 12) ที่คำสั่งจะทำงาน
Field ที่ 5ระบุ วันภายในสัปดาห์ (0 – 6) ที่คำสั่งจะทำงาน โดยเริ่มต้นที่ 0 = วันอาทิตย์ และสิ้นสุดที่ 6 = วันเสาร์
Field ที่ 6ระบุ ตัวคำสั่ง
การระบุเวลา

สำหรับ fields ที่กำหนดเวลาทั้ง 5 fields นั้น สามารถระบุเป็นค่าตัวเลข หรือ ใช้อักขระพิเศษมาช่วยในการระบุกำหนดการ ซึ่งรูปแบบที่เป็นไปได้ประกอบไปด้วย

รูปแบบที่เป็นได้การใช้งานตัวอย่างการระบุนาที
ค่าตัวเลขระบุค่าเวลาเฉพาะเจาะคง5หมายถึง นาทีที่ 5
*ระบุทุกค่าเวลาที่เป็นไปได้*หมายถึง ทุกนาที
,คั่นเพื่อระบุหลายค่าเวลา5,10หมายถึง นาทีที่ 5 และ 10
คั่นเพื่อระบุช่วงของเวลา5-10หมายถึง นาทีที่ 5,6,7,8,9 และ 10
/คั่นเพื่อระบุขั้นของเวลา*/5หมายถึง ทุก ๆ 5 นาที
ตัวอย่างกำหนดการ
5 * * * * echo helloเป็นการกำหนดให้คำสั่ง echo hello ทำงานที่นาทีที่ 5 ของทุกชั่วโมง
0 0 * * * echo helloเป็นการกำหนดให้คำสั่ง echo hello ทำงานทุกเที่ยงคืน
0 */2 * * * echo helloเป็นการกำหนดให้คำสั่ง echo hello ทำงานทุก ๆ 2 ชั่วโมงที่นาทีที่ 0

สำหรับตัวอย่างกำหนดการอื่น ๆ เพื่อน ๆ สามารถเข้ามาดูได้ที่ https://crontab.guru ซึ่งนอกจากจะมีตัวอย่างการระบุเวลาแล้ว เพื่อน ๆ ยังสามารถทดลองใส่การระบุเวลาของตนเองเพื่อตรวจว่าเป็นไปตามต้องการก่อนนำไปใช้จริงได้อีกด้วย


LAB ตั้งเวลา run Python script บน ubuntu

หลังจากที่เราได้เรียนรู้รูปแบบการเขียนกำหนดการภายในไฟล์ Crontab กันแล้ว เราก็จะมาลองตั้งกำหนดการให้ Python script

1) ทำการจัดเตรียม python script ที่จะใช้ในการทดลองนี้ โดยจะตั้งชื่อว่า hello_task.py

from datetime import datetime
print(f"Hello @ {datetime.now()}")

หากทดลอง run script ด้วยคำสั่ง $python3 จะพบว่า เป็นการพิมพ์ข้อความ “Hello @ วันเวลา ณ ขณะนั้น” ออกมายังหน้าจอ ดังภาพตัวอย่างข้างล่าง

2) ตรวจสอบ python path และ script path เพื่อใช้ในการเขียนกำหนดการ

โดยใช้คำสั่ง $which python3 ในการช่วยค้นหา python path และ $pwd ในการช่วยแสดง path ที่อยู่ ณ ปัจจุบัน

หากทดลอง run script โดยใช้ full path ที่หามาได้ ควรได้ผลลัพธ์เฉกเช่นเดิม ดังที่แสดงในภาพตัวอย่างข้างล่าง

3) ทำการตรวจสอบว่า cron service ทำงานอยู่

โดยใช้คำสั่ง $systemctl status cron

4) เข้าสู่ crontab เพื่อทำการเพิ่มกำหนดการ

โดยใช้คำสั่ง $crontab -e

หากเป็นการแก้ไขครั้งแรก ระบบจะให้เราเลือกว่าต้องการใช้ editor ชนิดใดในการแก้ไฟล์ crontab ซึ่งเพื่อน ๆ สามารถเลือกใช้ editor ที่ถนัดได้ หากไม่แน่ใจแนะนำให้เลือกใช้ nano ซึ่งเป็น editor ที่ง่ายที่สุด โดยมีปุ่มลัดที่จำเป็นได้แก่ ctrl+o เพื่อบันทึกไฟล์ และ ctrl+x เพื่อออกจาก editor

หลังจากเลือก editor เสร็จ ระบบจะทำการเปิดไฟล์ crontab ขึ้นมา ซึ่งจะยังไม่มีกำหนดการใด ๆ เราสามารถเขียนกำหนดการใหม่เพิ่มต่อจากบรรทัดล่างสุดได้เลย

5) เขียนกำหนดการเพื่อ run python script ทุก ๆ นาที

โดยที่เราจะเพิ่มคำสั่งให้ redirect output มายังไฟล์ hello_log.txt เพื่อบันทึกผลลัพธ์การทำงาน

# m h dom mon dow command
* * * * * /usr/bin/python3 /home/nj_gbdi_test/test_scheduling/hello_task.py >> /home/nj_gbdi_test/test_scheduling/hello_log.txt

เกร็ดความรู้: ในการ redirect ผลลัพธ์ไปยังไฟล์นั้น
>” จะทำการสร้างไฟล์ใหม่หากยังไม่มี หรือเขียนทับไฟล์เดิมหากมีไฟล์ชื่อดังกล่าวอยู่แล้ว
“>>” จะทำการสร้างไฟล์ใหม่หากยังไม่มี หรือเขียนต่อจากไฟล์เดิมหากมีไฟล์ชื่อดังกล่าวอยู่แล้ว

6) ทำการตรวจสอบการทำงานของ CRON

หลังจากผ่านไป 2-3 นาที ลองตรวจสอบดูว่า cron ได้ทำการสั่งงานคำสั่งตามที่เราระบุไว้หรือไม่  โดยที่เราสามารถไปตรวจสอบดูได้ทั้งที่ syslog หรือ log file ที่เราสร้างไว้

(a) ตรวจสอบดูที่ syslog โดยใช้คำสั่ง $grep CRON /var/log/syslog

จากตัวอย่างในรูป พบว่าคำสั่งที่เราระบุในไฟล์ crontab ถูกสั่งทำงานไป 3 รอบ ห่างกันรอบละ 1 นาที

(b) ตรวจสอบดูที่ log file ที่เราสร้างไว้ (จากการ redirect output) โดยการอ่านข้อมูลภายในไฟล์ ด้วยคำสั่ง อาทิ $more hello_log.txt

จากตัวอย่างในรูป พบผลลัพธ์จากการ run script 3 รอบ ห่างกันรอบละ 1 นาที

7) [optional] ทำการปรับแต่งคำสั่งในกำหนดการ ให้ผลลัพธ์ของการทำงานในแต่รอบถูก log เก็บไว้แยกไฟล์กัน พร้อมทั้งมีการบันทึก error ที่อาจเกิดขึ้นเก็บไว้ด้วย

  • ดยการเพิ่ม prefix วันที่และเวลาให้กับ ชื่อ log file (ที่เราจะ redirect output)
  • พร้อมทั้งเพิ่มการ redirect error มายัง log file ดังกล่าว

ทั้งนี้เนื่องจาก ในการทำงานจริงนั้น ผลลัพธ์ของ script อาจมีความยาวมาก พร้อมทั้งอาจเกิดข้อผิดพลาดในขณะทำงาน การบันทึก log file แยกกันในแต่รอบการทำงานเป็นวิธีนึงที่จะช่วยให้การค้นหาข้อผิดพลาดเมื่อ script เกิด error ง่ายขึ้น

# m h dom mon dow command
* * * * * /usr/bin/python3 /hhome/nj_gbdi_test/test_scheduling/hello_task.py > /home/nj_gbdi_test/test_scheduling/`date +\%Y\%m\%d\%H\%M\%S`_hello_task.log 2>&1

** ผู้สนใจสามารถศึกษาข้อมูลเพิ่มเติมเกี่ยวกับ backtick (`) และ date format ได้ **

หลังจากผ่านไป 1-2 นาที หากตรวจสอบ directory ที่เก็บ log files จะพบว่า log files ถูกจัดเก็บแยกกันแล้ว โดยมีวันเวลาที่ชื่อไฟล์ระบุรอบของการทำงาน

บทสรุป

ในบทความนี้ เราก็ได้รู้จัก CRON เครื่องมือใน Linux ที่ช่วยให้เราสามารถกำหนดการทำงานของ Python script หรือคำสั่งต่าง ๆ ได้อย่างอัตโนมัติ ซึ่งวิธีการเบื้องต้นไม่ได้ยากอะไรเลย เพียงแค่เราเข้าไปแก้ไขไฟล์ Crontab และระบุกำหนดการทำงานของ script (เวลา + คำสั่ง run script) ให้ถูกต้อง

หวังว่าบทความนี้ จะมีประโยชน์ต่อผู้ที่ต้องการเริ่มต้น schedule python script รวมทั้งต่อยอดไปยังการ schedule commands อื่น ๆ กันนะคะ

References

https://en.wikipedia.org/wiki/Cron

https://www.adminschoice.com/crontab-quick-reference

เนื้อหาโดย ณัฐพัชร์ เศรษฐเสถียร
ตรวจทานโดย พีรดล สามะศิริ

Data Scientist
Government Big Data institute (GBDi)

Recommended Posts