ช่วงนี้ผมกำลังทำระบบ Hermes Agent ขึ้นมาใช้งานอยู่ และกำลังทดสอบให้มัน backup ตัวเองเป็นระยะ
ตัว Hermes ของผมอยู่บน Mac mini เลยคิดว่าจะใช้ cron ของ macOS ตั้งเวลาให้ script backup ทำงาน ก็น่าจะเป็นงานตรงไปตรงมา
คำว่า “ก็น่าจะ” นี่แหละ ที่มักตามมาด้วยเวลาหลายชั่วโมงใน Terminal
พอตั้งเสร็จ cron กลับไม่ทำงาน
ผมลองรัน script เดิมจาก Terminal แล้วมัน backup ได้ตามปกติ ไฟล์ออกครบ ไม่มี error อะไร พอปล่อยให้ cron เป็นคนเรียกกลับเงียบไปเลย
เงียบแบบไม่ทิ้งแม้แต่ error ไว้ให้เรารู้สึกว่าตัวเองยังมีความหวัง
ตอนแรกผมไล่ดู cron syntax อยู่พักหนึ่ง เพราะมันเป็นผู้ต้องสงสัยอันดับแรกเสมอ
สุดท้ายปัญหาไม่ได้อยู่ที่ cron syntax แต่มันเป็นเรื่อง permission ของ macOS ที่ผมไม่ได้คิดถึง
cron บน macOS ไม่ได้มีสิทธิ์เท่ากับ Terminal
เวลารัน script จาก Terminal เรามักคิดว่า ถ้ามันทำงานตรงนี้ได้ cron ก็ควรทำได้เหมือนกัน
แต่ cron เป็น background process อีกตัวหนึ่ง มันไม่ได้รับสิทธิ์เข้าถึงไฟล์แบบเดียวกับ Terminal เสมอไป
Terminal เหมือนเราเดินเข้าบ้านพร้อมกุญแจ ส่วน cron เหมือนเพื่อนที่มายืนกดกริ่งหน้าบ้านตอนตีสาม แม้ตั้งใจมาช่วย แต่ก็ไม่ได้แปลว่าจะได้เข้ามา
ถ้า script backup ต้องอ่านหรือเขียนไฟล์ใน Desktop, Documents, Downloads หรือ external drive, macOS อาจบล็อกมันไว้โดยที่ไม่ส่ง error ที่ชัดเจนกลับมา
อาการของ cron ที่ติด permission บน macOS
อาการที่ผมเจอค่อนข้างหลอกตา
crontab -lมี job อยู่ตามปกติ- รัน script ด้วยมือแล้วทำงาน
- ถึงเวลาที่ตั้งไว้แล้วไม่มีไฟล์ backup ใหม่
- ไม่มี error โผล่มาให้ตามต่อ
ถ้าเจอแบบนี้ ผมว่าอย่าเพิ่งแก้ schedule หรือเปลี่ยน cron expression หลายรอบ เพราะปัญหาอาจไม่อยู่ตรงนั้นเลย
ผมเริ่มจากให้ cron เขียน log ก่อน
สิ่งแรกที่ช่วยได้มากคือแยกให้ชัดว่า cron ไม่ทำงาน หรือ cron ทำงานแล้ว script ต่างหากที่พัง
ผมลองตั้ง job เล็ก ๆ ให้เขียนเวลาไปที่ /tmp ทุกนาที
* * * * * /bin/date >> /tmp/cron-test.log 2>&1
จากนั้นรอสักครู่แล้วเปิดดู
cat /tmp/cron-test.log
ถ้าเวลาใหม่เพิ่มเข้ามาเรื่อย ๆ ก็แปลว่า cron ยังทำงานอยู่ และยังไม่ถึงขั้นต้องจัดงานศพให้มัน
จากนั้นค่อยไล่ดู script, path, environment และสิทธิ์ของไฟล์ปลายทางต่อ
cron ควรใช้ absolute path และเก็บ error ลง log
cron ไม่ได้มี environment เหมือน session ที่เราเปิด Terminal อยู่
คำสั่งบางตัวที่พิมพ์แล้วทำงานได้ อาจหาไม่เจอเมื่อ cron เป็นคนรัน เพราะ PATH ไม่เหมือนเดิม หรือ HOME ไม่ได้ชี้ไปที่ที่เราคิด
ผมเลยเขียน cron ให้ระบุทุกอย่างตรง ๆ ไปเลย
PATH=/usr/local/bin:/usr/bin:/bin
HOME=/Users/yourname
0 */6 * * * /bin/bash /Users/yourname/scripts/backup-hermes.sh >> /Users/yourname/logs/hermes-backup.log 2>&1
จุดประสงค์คือระบุ path ให้ชัด และเก็บทั้ง output กับ error ลง log
พอมี log แล้ว เวลาอะไรพังจะไม่ต้องนั่งเดาว่า cron ถูกเรียกหรือไม่, script รันหรือไม่รัน, หรือมันหา command ไม่เจอ
Full Disk Access อาจเป็นสิ่งที่ขาดไป
ถ้า script backup ต้องอ่านหรือเขียนไฟล์ในพื้นที่ที่ macOS ป้องกันไว้ อาจต้องเพิ่ม Full Disk Access ให้ cron
เข้าไปที่ System Settings แล้วเปิด Privacy & Security จากนั้นเลือก Full Disk Access
กดปุ่มเพิ่มรายการ แล้วใช้ Command + Shift + G เพื่อไปที่ path นี้
/usr/sbin
จากนั้นเลือก cron และเปิดสิทธิ์ให้มัน
บทความที่ผมไปเจอแนะนำให้เพิ่ม Full Disk Access ให้ Terminal ด้วย เพราะเราใช้ Terminal จัดการ crontab อยู่แล้ว [1]
ฝั่ง macOS ไม่ได้ใจร้าย มันแค่ตั้งใจทำหน้าที่ รปภ. มากไปหน่อย และ cron ของเราดันลืมพกบัตรผ่าน
ผมจะไม่แนะนำให้เปิดสิทธิ์นี้ทิ้งไว้กับทุกอย่าง เพราะ Full Disk Access ให้สิทธิ์ค่อนข้างกว้าง ถ้า backup ไม่จำเป็นต้องแตะโฟลเดอร์ที่ถูกป้องกัน ก็อาจย้ายปลายทางไปไว้ใน directory ที่เข้าถึงง่ายกว่าแทน
ผมนำวิธีนี้กลับมาใช้กับ Hermes Agent backup ยังไง
หลังแก้ permission แล้ว ผมยังไม่ตั้ง backup เป็นทุก 6 ชั่วโมงทันที
ผมลดรอบให้ cron เรียก script ทุกนาทีชั่วคราว แล้วเปิด log ดูว่ามันเริ่มสร้าง backup ได้จริงหรือไม่
พอเห็นว่า cron เรียก script ได้, script เข้าถึงไฟล์ได้ และ log ไม่มี error ค่อยเปลี่ยนกลับไปเป็นรอบเวลาที่ต้องการ
ถ้าทดสอบด้วย schedule รายวันตั้งแต่แรก แล้วมันยังพังอยู่ เราอาจต้องรอข้ามวันกว่าจะรู้ตัว ซึ่งเป็นวิธีเสียเวลาที่ไม่จำเป็นนัก
เช็กลิสต์ก่อนปล่อย cron backup บน macOS
- job แสดงอยู่ใน
crontab -l - cron มี log ยืนยันว่าถูกเรียก
- script ใช้ absolute path
- stdout และ stderr ถูกเก็บลง log
- path ปลายทางไม่ได้ถูก macOS บล็อก
cronมี Full Disk Access ถ้างานจำเป็นต้องเข้าถึงไฟล์ที่ถูกป้องกัน- ทดสอบด้วยรอบเวลาสั้นก่อน แล้วค่อยเปลี่ยนเป็น schedule จริง
สรุป
กรณีของผม cron ไม่ได้พัง และ script backup ของ Hermes Agent ก็ไม่ได้มีปัญหา
ตัวที่ขวางอยู่คือ macOS ไม่ยอมให้ background process เข้าถึงไฟล์บางตำแหน่ง
ถ้าตั้ง cron แล้วเงียบ ให้เริ่มจาก log ทดสอบง่าย ๆ ก่อน จากนั้นค่อยเช็ก path, environment และ permission ทีละจุด
อย่างน้อยพอเจอต้นเหตุแล้ว จะได้เลิกแก้ cron expression รอบที่สิบ ทั้งที่มันไม่ได้ทำอะไรผิดเลย
อ้างอิง
[1] https://dev.to/trueqap/how-to-run-cron-on-macos-in-2025-a-complete-guide-2b8e

Member discussion