สาเหตุหลักที่รันด้วย caffeinate -dimsu บน macOS แล้วสคริปต์ยังหยุดทำงานหรือทำงานไม่ต่อเนื่องเมื่อทิ้งเครื่องไว้ เกิดจาก พฤติกรรมการจัดการพลังงานระดับ OS (App Nap / Sleep Mode) ผสมกับคอขวดของ HTTP Requests และ Ollama โดยมีจุดที่ต้องตรวจสอบและแก้ไขดังนี้ครับ
สาเหตุหลักที่ทำให้เหมือนหยุดทำงาน
- พับฝาจอ MacBook (Clamshell Sleep)
- แม้จะใส่
caffeinate -dimsuแต่ถ้าเป็น MacBook แล้วไม่ได้เสียบสายชาร์จ (Power Adapter) ไว้ หรือไม่ได้ต่อจอนอก เมื่อพับฝาลง ระบบจะบังคับ System Sleep ทันที คำสั่ง caffeinate ทั่วไปจะไม่สามารถฝืนฮาร์ดแวร์ sleep ตอนพับฝาได้
- แม้จะใส่
- macOS App Nap บังคับจำกัดการทำงานของ Terminal
- เมื่อหน้าต่าง Terminal หรือแอปที่รันอยู่ไม่ได้อยู่โฟกัสด้านหน้า (Backgrounded) หรือหน้าจอดับลง macOS จะเข้าสู่โหมดประหยัดพลังงาน บีบ Thread Priority และลด I/O ของโปรเซสนั้นลง ทำให้ตัวรันแทบหยุดนิ่ง
- Wi-Fi / Network Drop ตอนหน้าจอดับ
- บน Apple Silicon macOS มักจะตัดหรือลดแบนด์วิดท์ Wi-Fi เมื่อไม่ได้ใช้งาน ทำให้ Request ที่ส่งไปยัง WordPress REST API หรือดึง Reference ค้างไปจน Timeout
- Ollama ค้างหรือหมด Timeout (600 วินาที)
- ในโค้ดมีการตั้ง
timeout=600(10 นาที) ต่อ 1 call ของ Ollama หาก Model รันโมเดลขนาดใหญ่ (gemma4:latest) แล้ว CPU/GPU โดน Throttle จากความร้อนหรือประหยัดพลังงาน ตัวสคริปต์จะค้างนิ่งเพื่อรอ Response นานเป็นสิบนาที จนดูเหมือนโปรแกรมไม่ทำงาน
- ในโค้ดมีการตั้ง
วิธีแก้ไขการตั้งค่าบน macOS
ก. กรณีใช้งานบน MacBook
- เสียบสายชาร์จไว้เสมอ ขณะรันงาน Batch Process ระยะยาว
- อย่าพับฝาจอลง (ยกเว้นต่อจอนอก, เมาส์, คีย์บอร์ด และเสียบไฟ เพื่อเข้า Clamshell mode เต็มรูปแบบ)
ข. ปิด App Nap ให้กับ Terminal / iTerm2
รันคำสั่งใน Terminal เพื่อไม่ให้ระบบลด Priority ของ Terminal ตอนทิ้งเครื่องไว้
Bash
BASH / Shell
# สำหรับ Terminal ค่าเริ่มต้นของ macOS
defaults write com.apple.Terminal NSAppSleepDisabled -bool YES
# หรือถ้าใช้ iTerm2
defaults write com.googlecode.iterm2 NSAppSleepDisabled -bool YES
ค. สั่งรันด้วย caffeinate แบบระบุโปรเซสให้ผูกติดโดยตรง
คำสั่งเดิมที่ใช้ดีอยู่แล้ว แต่แนะนำให้เพิ่ม flag ป้องกันการ sleep ของฮาร์ดแวร์ขณะเสียบชาร์จ:
Bash
BASH / Shell
caffeinate -dis -w $$ &
python3 wp_loop_post_update.py --start-id 3512 --mode verify
หรือรันแบบเดิมโดยมั่นใจว่าเสียบสายชาร์จและเปิดฝาจอไว้
Bash
BASH / Shell
caffeinate -dimsu python3 wp_loop_post_update.py --start-id 3512 --mode verify
3. จุดที่ควรปรับปรุงในโค้ด Python เพื่อไม่ให้ค้าง
ในสคริปต์มีจุดที่ Request อาจค้างเงียบ ๆ นานเกินไป ทำให้ดูเหมือนโปรเซสหยุดเดิน
1) เพิ่ม Keep-Alive และ Retry Strategy ให้กับ SESSION
ป้องกันอาการ Connection หลุดเงียบ ๆ จากระบบ Network
Python
BASH / Shell
from urllib3.util import Retry
from requests.adapters import HTTPAdapter
retries = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retries, pool_connections=10, pool_maxsize=10)
SESSION.mount("http://", adapter)
SESSION.mount("https://", adapter)
2) ลด Timeout ของ Ollama และใส่ Log แสดงความคืบหน้าระหว่างรอ
ในฟังก์ชัน generate_article_content_with_llm มี timeout=600 ถ้า LLM เจนช้า คุณจะไม่เห็นเอาต์พุตเลยตลอด 10 นาที แนะนำให้ลดลงเหลือประมาณ 180 หรือ 240 วินาที และพิมพ์ Log บอกก่อนยิง API:
Python
BASH / Shell
print(f" ⏳ กำลังส่ง Prompt ให้ Ollama ({model_name})...")
res = SESSION.post(OLLAMA_URL, json=payload, timeout=240)
3) เปิด Unbuffered Mode ใน Python
เวลาทิ้งรันไว้นาน ๆ บางครั้งเอาต์พุตจะไม่ยอม Flush ออกมาที่หน้าจอ Terminal จนกว่าบัฟเฟอร์จะเต็ม ทำให้มองไม่เห็น Log ล่าสุด
รันด้วย flag -u:
Bash
BASH / Shell
caffeinate -dimsu python3 -u wp_loop_post_update.py --start-id 3512 --mode verify