SCHEDULING: ตั้งเวลา run Python script บน Linux ด้วย CRON กัน !

หลังจากที่เพื่อน ๆ ได้เขียนโปรแกรมมาระยะนึง ก็อาจจะเกิดคำถามว่า “จะเป็นไปได้ไหมที่เราจะตั้งเวลา (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 จะจัดเก็บกำหนดการทำงานของแต่ละคำสั่งไว้ในแต่ละบรรทัด โดยที่แต่ละบรรทัดจะประกอบไปด้วย 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
เนื้อหาโดย ณัฐพัชร์ เศรษฐเสถียร
ตรวจทานโดย พีรดล สามะศิริ