←→ Underneath: Background Apps · คู่มือ Mac ทั้งหมด
ทำไมแอปจึงกลับมาหลังจากคุณเริ่มการทำงาน Mac ใหม่
คุณออกจากแอปแล้ว และยังบังคับออกในตัวติดตามกิจกรรมด้วย แต่สองวินาทีต่อมา หรือหลังการเริ่มการทำงานใหม่ครั้งถัดไป แอปก็กลับมาทำงานอีก มีบางอย่างตั้งใจเริ่มแอปนั้น และบน Mac สิ่งนั้นแทบจะเป็น launchd เสมอ
คำตอบสั้นๆ: แอปนั้นมีงาน launchd โดย RunAtLoad จะเริ่มงานทุกครั้งที่เข้าสู่ระบบ และ KeepAlive จะเริ่มงานใหม่ทุกครั้งที่หยุด การออกจากโปรเซสไม่ได้เปลี่ยนงาน หากต้องการหยุดอย่างถาวร ให้ปิดใช้งาน ไม่ใช่โปรเซส
launchd คืออะไร
launchd คือโปรเซสแรกที่ macOS เริ่ม (โปรเซส ID 1) และเป็นตัวเริ่มเกือบทุกอย่างที่เหลือ launchd อ่านไฟล์ .plist ขนาดเล็กที่เรียกว่างาน ซึ่งบอกว่าจะเรียกใช้อะไรและเมื่อไร แต่ละงานมีป้ายกำกับ ซึ่งเป็นชื่อที่ไม่ซ้ำกัน เช่น com.google.keystone.agent
แอปจะติดตั้งงานไว้ใน ~/Library/LaunchAgents, /Library/LaunchAgents หรือ /Library/LaunchDaemons หรือลงทะเบียนงานจากภายใน bundle ของแอปเอง
คีย์ที่ทำให้แอปกลับมา
นี่คือตัวอย่าง launch agent ทั่วไป:
<key>Label</key>
<string>com.example.helper</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Example.app/Contents/MacOS/Helper</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
| คีย์ | ผล | สิ่งที่คุณเห็น |
|---|---|---|
RunAtLoad | เริ่มงานทันทีที่โหลด ซึ่งก็คือทุกครั้งที่เข้าสู่ระบบ (เอเจนต์) หรือเริ่มเครื่อง (daemon) | แอปอยู่ที่นั่นทุกครั้งหลังเริ่มการทำงานใหม่ |
KeepAlive = true | เริ่มโปรเซสใหม่ทุกครั้งที่ออก | บังคับออกก็ไม่ได้ผล แอปกลับมาในไม่กี่วินาที |
KeepAlive แบบมีเงื่อนไข | เริ่มใหม่เฉพาะบางกรณี เช่น หลังแครช (SuccessfulExit = false) หรือขณะที่เครือข่ายเชื่อมต่ออยู่ | บางครั้งกลับมา บางครั้งไม่ |
StartInterval | ทำงานทุก N วินาที | ปรากฏขึ้น ทำงานสั้นๆ แล้วหายไป วนซ้ำ |
StartCalendarInterval | ทำงานตามเวลาที่กำหนด เหมือน cron | ปรากฏขึ้นเวลาเดิมทุกวัน |
WatchPaths | ทำงานเมื่อไฟล์หรือโฟลเดอร์เปลี่ยนแปลง | ปรากฏขึ้นหลังจากคุณทำอะไรบางอย่างที่ไม่เกี่ยวข้อง |
launchd จะรอประมาณ 10 วินาทีระหว่างการเริ่มใหม่แต่ละครั้งของงานที่ออกซ้ำๆ งาน KeepAlive จึงอาจดูเหมือน “กะพริบ” ได้ด้วย
เหตุผลอื่นที่แอปกลับมา
- เปิดเมื่อเข้าสู่ระบบ แอปอยู่ใน การตั้งค่าระบบ › ทั่วไป › รายการเข้าสู่ระบบและส่วนขยาย macOS จะเปิดแอปทุกครั้งที่เข้าสู่ระบบ
- เปิดหน้าต่างอีกครั้งเมื่อเข้าสู่ระบบกลับเข้ามา ช่องนี้ในหน้าต่างโต้ตอบเริ่มการทำงานใหม่และปิดเครื่องจะกู้คืนทุกแอปที่เปิดอยู่
- แอปเพิ่มตัวเองกลับเข้าไป การตั้งค่า “เริ่มเมื่อเข้าสู่ระบบ” ของแอปเองจะลงทะเบียนแอปใหม่ทุกครั้งที่แอปทำงาน
- ตัวช่วยเปิดแอปหลัก ตัวช่วยเบื้องหลังขนาดเล็กเริ่มทำงานก่อน แล้วจึงเปิดแอปตัวเต็ม เช่น เพื่อแสดงสถานะการซิงค์
- บริการ Homebrew
brew services startจะเขียน launch agent ที่มีRunAtLoadหยุดได้ด้วยbrew services stop <name>
หาว่าเป็นตัวไหน
- หาป้ายกำกับของงาน เรียกใช้
launchctl list | grep -i exampleโดยใช้ส่วนหนึ่งของชื่อแอปหรือชื่อนักพัฒนา คอลัมน์ที่สามคือป้ายกำกับ - อ่านข้อมูลงาน:
ดูที่launchctl print gui/$(id -u)/com.example.helperpath(ไฟล์ plist),state,runs(จำนวนครั้งที่เริ่ม) และlast exit codeจำนวนครั้งที่สูงมักหมายถึงKeepAlive - เปิด plist แล้วตรวจสอบ
RunAtLoad,KeepAliveและคีย์ช่วงเวลา - หากไม่มีงาน ให้ตรวจสอบ “เปิดเมื่อเข้าสู่ระบบ” และการตั้งค่าของแอปเอง
หยุดกับปิดใช้
| สิ่งที่คุณทำ | กลับมาหรือไม่ |
|---|---|
| ออกหรือบังคับออกจากโปรเซส | ใช่: ทันทีหากมี KeepAlive, เมื่อเข้าสู่ระบบครั้งถัดไปหากมี RunAtLoad |
launchctl bootout gui/$(id -u)/label | ตอนนี้ไม่ แต่กลับมาเมื่อเข้าสู่ระบบครั้งถัดไปหากมี RunAtLoad |
launchctl disable gui/$(id -u)/label + bootout | ไม่ จนกว่าคุณจะเรียกใช้ launchctl enable |
| ย้าย plist ออกจาก LaunchAgents + bootout | ไม่ จนกว่าคุณจะย้ายกลับ |
| ปิดใน “อนุญาตในพื้นหลัง” | ไม่ จนกว่าคุณจะเปิดอีกครั้ง |
คำสั่งทีละขั้นตอนอยู่ในวิธีปิดใช้ launch agent อย่างปลอดภัย
คำถามที่พบบ่อย
ทำไมโปรเซสจึงเริ่มใหม่ทันทีหลังจากฉันสั่งออกในตัวติดตามกิจกรรม
เพราะงาน launchd ของโปรเซสนั้นตั้งค่า KeepAlive ไว้ launchd จะเฝ้าดูโปรเซสและเริ่มใหม่เมื่อโปรเซสออก ให้หยุดงานด้วย launchctl bootout แทนการสั่งออกจากโปรเซส
RunAtLoad หมายถึงอะไร
RunAtLoad คือคีย์ใน plist ของ launchd เมื่อมีค่าเป็น true launchd จะเริ่มงานทันทีที่โหลด plist ซึ่งสำหรับ launch agent หมายถึงทุกครั้งที่คุณเข้าสู่ระบบ
KeepAlive หมายถึงอะไร
KeepAlive บอกให้ launchd คอยให้งานทำงานอยู่ตลอด หากโปรเซสออกหรือถูกฆ่า launchd จะเริ่มใหม่ และยังกำหนดเป็นชุดเงื่อนไขได้ด้วย เช่น เริ่มใหม่เฉพาะหลังจากแครช
การหยุดกับการปิดใช้ launch agent ต่างกันอย่างไร
การหยุด (launchctl bootout) จะยกเลิกการโหลดงานจนถึงการเข้าสู่ระบบหรือการเริ่มการทำงานใหม่ครั้งถัดไป การปิดใช้ (launchctl disable หรือย้าย plist ออกจาก LaunchAgents) จะทำให้งานไม่ถูกโหลดอีกหลังเริ่มการทำงานใหม่