2009-07-09 11 views
11

セッションレベルのGUIエージェントをルートレベルのデーモンから起動または停止できる必要があります。GUIセッションを持つすべてのユーザーの起動エージェントの起動/停止

同様の問題については、here,hereおよびhereと記載されています。私が行うことができるようにしたいどのような

は基本的に

for num in `ps ax | grep [s]bin/launchd | cut -c 1-5`; 
do 
    if [ $num -ne 1 ]; 
    then 
     sudo launchctl bsexec $num launchctl (un)load -S Aqua /Library/LaunchAgents/com.mycompany.mydaemon.plist; 
    fi; 
done 

ですが、これだけ開始/ 1インスタンスを停止し、それが現在のGUIセッションでrootとして実行されます。私はオフにそこにsudoを残した場合、私は

task_for_pid() (os/kern) failure 
Couldn't switch to new bootstrap port: (ipc/send) invalid port right 

を取得開始私は(コマンドをロード/アンロードでbsexecから二次スクリプトを呼び出す含む)bsexecの他の順列の様々ないじり試してみたが、私はすることができますインスタンスをroot以外のものとして起動することは決してありません。別のGUIセッションでは使用しないでください。

また、私はsu - <user> ...sudo -u <user> ...を使いこなそうとしましたが、そこには運がありませんでした(多くの人が上記のリンクされた記事や他の場所で議論しています)。

誰にも考えがありますか?

EDIT: グラハム・リーによって、以下の提案として、私はラッパーツールでこれをやってみましたが、私は次のエラーを取得する:

launch_msg(): Socket is not connected 

これは、私は、コマンドラインコマンド、ラッパー、およびスクリプトです用いた(501は、別のユーザのユーザIDと63093のlaunchdのPIDがシステムにログインしている):

コマンドライン:

sudo launchctl bsexec 63093 /path/TestSetUIDAndExecuteTool 501 /path/LoadBillingDialogAgent 

ラッパー:

#import <Foundation/Foundation.h> 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    if (argc != 3) { 
    NSLog(@"Tool called with improper arguments"); 
    return -1; 
    } 

    int uid = [[NSString stringWithUTF8String:argv[1]] intValue]; 
    // TODO: REMOVE 
    NSLog(@"Setting uid to |%i|", uid); 

    setuid(uid); 
    // TODO: REMOVE 
    char *command = (char *)argv[2]; 
    NSLog(@"Executing command |%s|", command); 
    system(command); 

    [pool drain]; 
    return 0; 
} 

スクリプト:

/bin/launchctl load -S Aqua /Library/LaunchAgents/com.company.agent.plist 

答えて

6

launchctl bsexecを使用しては正しいですが、「本当の」エージェントの実行可能ファイルを実行する前に、ターゲットユーザーにUIDをドロップするラッパーツールを起動する必要があります。ああ、おそらくloginwindowプロセスを探しているほうが良いでしょう。それらはログインセッションのリーダーです(しかし、launchdでも動作する可能性が高いですが)。

+0

私は 'launch_msg():ソケットが接続されていません 'というエラーが表示されます –

+0

私はUIDをcorrentの方法で削除していますか? –

+0

実際、私はこれを考え出しました。私が設定したテスト環境は、本当のルートレベルのデーモンと全く同じではないようです。助けてくれてありがとう。 –

4

ユーザーごとのlaunchdインスタンスが、launchctlがTerminalから起動されたのと同じブートストラップ名前空間内で実行されていないように見えます。 PIDドナーといくつかのsudo魔法としてDock.appを使用することにより

ps aux | grep Dock.app | grep -v grep | awk '{system("sudo launchctl bsexec "$2" sudo -u "$1" launchctl load -S Aqua /Library/LaunchAgents/com.my.agent.plist")}' 

実行中のすべてのセッションでエージェントを起動することが可能です。

きちんとしていませんが、機能します。

更新:10.7では動作しません。はい、エージェントが起動されますが、正しいコンテキストではないことがわかります。

+1

10.9では動作しません。エージェントは異なるコンテキストで起動されます。たとえば、UIは表示されません(エラーは表示されず、表示されません)。 – esmirnov

1

私は同じ問題を抱えていました。 これを解決するには、launchdが開始したプロセスのPIDである "under" launchdというPIDを使用します。

「launchctl bsexec」にコミットしたpidは、適切なブートストラップを見つけるために使用されます。あなたがルート起動されたブートストラップで作業するよりも、(ユーザコンテキストからの)launchdのPIDを使用する場合。 peを使用している場合。ファインダーやドックpidを使用する場合は、この「ユーザーごと」のブートストラップで作業することができます

3

ここでの説明とthis scriptに基づいて、私はラッパーツールが必要であるとは思わなかった。これらの2つのbashスクリプトは他の人にも役立つかもしれません。

Unload Agents

#!/bin/bash 
for id in `ps aux | grep -v grep | grep MyAgent | awk {'print $2'}` 
do 
    launchctl bsexec $id launchctl unload /Library/LaunchAgents/myAgent.plist 
done 

あなたの打ち上げエージェントの名を持つ 'myagentという' 交換してください。ルートデーモンから呼び出され

Load Agents

#!/bin/bash 
for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do 

    pid=$(echo $pid_uid | cut -d, -f1) 
    uid=$(echo $pid_uid | cut -d, -f2) 

    launchctl bsexec "$pid" chroot -u "$uid"/launchctl load /Library/LaunchAgents/myAgent.plist 
done 

、これは、ログインしているすべてのユーザーのためにmyAgent.plistで参照起動エージェントをロードし、アンロードされます。

OS X El Capitan(10.11)では 'rootless'なので、bsexecの使用はもう機能しなくなる可能性がありますが、10.10までは問題ありません。

+4

エルキャピタン(10.11)の場合 'launchctl bootstrap gui/$ uid/Library/LaunchAgents/myAgent.plist' – vrrathod

+0

ありがとう@vrrathod、それはお勧めです。 – TheDarkKnight

関連する問題