2011-10-25 25 views
5

Tôi có một LaunchDaemon. Khi nó chạy, nó sẽ kiểm tra nếu SIMBL được cài đặt. Nếu SIMBL không được cài đặt, nó sử dụng NSTask để chạy/usr/sbin/installer trên SIMBL.pkg.Làm thế nào bạn có thể khởi động LaunchAgent lần đầu tiên mà không cần khởi động lại, khi mã của bạn chạy dưới dạng LaunchDaemon?

kịch bản postflight SIMBL của sau đó cố gắng để chạy một lệnh tải launchctl để bắt đầu LaunchAgent SIMBL ngay lập tức:

sudo -u "$USER" -- /bin/launchctl load -F -S Aqua -D user "${LAUNCHD_PLIST}" 

này thất bại, bởi vì môi trường NSTask LaunchDaemon tôi không có $ USER bộ.

Nếu tôi có daemon tôi phát hiện người sử dụng hiện tại với khung System Configuration và vượt qua nó để NSTask với setEnvironment, launchctl lỗi trên tôi:

Bug: launchctl.c:2325 (23930):13: (dbfd = open(g_job_overrides_db_path, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1 

Tôi nhận ra một daemon, theo định nghĩa, nên không hoạt động trong phiên người dùng. Theo cùng một mã thông báo, Apple dường như đề xuất LaunchAgents làm đối tượng trợ giúp cho LaunchDaemons, để thực hiện công việc của người dùng đó. Có cách nào để có được một đại lý như vậy và chạy ngay lập tức?

Tôi có tất cả các địa chỉ .plists ở đúng nơi (chúng bắt đầu chạy sau khi khởi động lại, lần tiếp theo launchctl thực hiện tải thường xuyên) vì vậy ý ​​tưởng đầu tiên của tôi là chỉ cần cho launchctl tải lại. Nhưng all the code to do that is commented out in launchctl.c:

// { "reload",   reload_cmd,    "Reload configuration files and/or directories" }, 

...

* In later versions of launchd, I hope to load everything in the first pass, 
* then do the Bonjour magic on the jobs that need it, and reload them, but for now, 
* I haven't thought through the various complexities of reloading jobs, and therefore 
* launchd doesn't have reload support right now. 

Trả lời

6

Oh thế nào launchd làm tôi điên ....

Để cắt để đuổi theo, sau nhiều nghiên cứu và thử nghiệm, đây là cách tôi làm điều đó trên 10.5+:

# If possible, tell launchd to start the LaunchAgent. This will fail on 10.4. 
# $F[0] is the pid 
# $F[1] is the username 
# $F[2] is the first word of the command 
ps -ww -A -opid,user,command | \ 
    perl -nae 'if($F[2] =~ /\bloginwindow\b/) { system(
    qq(launchctl bsexec $F[0] su $F[1] -c "launchctl load -w <your_plist>")) 
}' 

Tôi không tìm thấy cách nào để đạt được điều này trực tiếp trên 10.4. Tôi lừa trên 10.4 và chỉ chạy thứ mà LaunchAgent sẽ chạy, mặc dù nó có giao diện đồ họa và bạn không được phép làm điều đó (dù sao bạn cũng có thể trong 10.4-10.6; bạn không thể trong 10.7). Vào 10.4, LaunchAgent hoạt động chính xác sau lần khởi động lại kế tiếp.

Mã trên tìm kiếm loginwindow quy trình và sử dụng bsexec để chạy các lệnh trong các ngữ cảnh đó. Hãy nhớ rằng với Chuyển đổi người dùng nhanh, có thể có nhiều bối cảnh.

Một số liên kết hữu ích:

  • Daemons and Services Programming Guide. Bạn phải đọc nó, nhưng nó sẽ không thực sự trả lời bất kỳ câu hỏi khó. Nhưng nó sẽ ít nhất cung cấp cho bạn gợi ý tại nơi tất cả mọi thứ nằm.
  • TN2083. Đây là một tài liệu buồn bã làm tăng nhiều câu hỏi khi nó trả lời, nhưng là phúc âm và bắt buộc đọc cho bất cứ ai bước vào vực thẳm của launchd.
  • Starting/stopping a launchd agent for all users with GUI sessions. Điều này có một số liên kết hữu ích khác và giải thích.

IMO, launchd là một trong những "ý tưởng tuyệt vời" tồi tệ nhất mà Apple từng triển khai. Ý tưởng này rất hữu ích, nhưng API là khủng khiếp.

+1

Với OS X "El Capitan" 10.11 (15A204h) có vẻ như "launchctl bsexec" không hoạt động nữa.Có lý do tại sao bước này là bắt buộc không? – yairchu

+1

Đó là phần khởi động lại tác nhân ở đúng ngữ cảnh. Nếu không có điều đó, bạn không khởi động lại như OP được yêu cầu. Tôi không biết cách nào (nếu có) điều này có thể xảy ra vào ngày 10.11. –

+0

có vẻ như có một cách để làm điều đó trên 10.11: 'launchctl bootstrap gui/\' stat -f% u \ ''. từ http://stackoverflow.com/questions/1106638/starting-stopping-a-launchd-agent-for-all-users-with-gui-sessions#comment51143118_31534614 – yairchu

Các vấn đề liên quan