我有一个bash脚本,我想在OS X上使用launchd plist文件运行.我遇到的问题是bash脚本包含sudo命令,它阻止它运行.例如,我的bash脚本如下所示:
#!/bin/bash
sudo /opt/local/bin/bindfs -u user1 /Library/WebServer/Documents/user1 /vhosts/user1/public_html
sudo /opt/local/bin/bindfs -u user2 /Library/WebServer/Documents/user2 /vhosts/user2/public_html
我的com.test.bindfs.plist文件看起来像这样(用Lingon创建):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>GroupName</key>
    <string>admin</string>
    <key>Label</key>
    <string>com.jamespayne.bindfs</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/bindfs.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
我已经检查过该脚本的工作原理是在启动后运行它并输入密码,但它不会在启动时运行.launchd plist正在运行,但它出现以下错误:
sudo:没有tty存在且没有指定askpass程序
任何人都知道如何使这个工作或为什么我可能会得到这个错误.谢谢.
我的申请分为两部分.主要应用程序和帮助工具.帮助工具执行具有提升权限的任务.
launchd plist看起来像这样:(仅包括重要设置.)
<key>UserName</key>
<string>root</string>
<key>ProgramArguments</key>
<array>
    <string>/Library/PrivilegedHelperTools/helperTool</string>
</array>
<key>Sockets</key>
<dict>
    <key>IPC</key>
    <dict>
        <key>SockPathName</key>
        <string>/tmp/TheSocket</string>
    </dict>
</dict>
有没有办法为套接字的每个连接启动一个新的帮助器实例?
或者,是否存在用于处理多个请求的现有模板?(我现在正在做这个,这是很多丑陋的代码.)
我有一个LaunchDaemon.运行时,它会检查是否安装了SIMBL.如果未安装SIMBL,则使用NSTask在SIMBL.pkg上运行/ usr/sbin/installer.
然后SIMBL的postflight脚本尝试运行launchctl load命令立即启动SIMBL的LaunchAgent:
sudo -u "$USER" -- /bin/launchctl load -F -S Aqua -D user "${LAUNCHD_PLIST}"
这失败了,因为我的LaunchDaemon的NSTask环境没有设置$ USER.
如果我让我的守护进程使用系统配置框架检测当前用户并使用setEnvironment将其传递给NSTask,则startctl会对我产生错误:
Bug: launchctl.c:2325 (23930):13: (dbfd = open(g_job_overrides_db_path, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1
根据定义,我意识到守护进程不应该在用户会话中运行.出于同样的原因,Apple似乎推荐LaunchAgents作为LaunchDaemons的辅助对象,以进行该用户会话工作.有没有办法让这样的代理立即运行?
我把所有的.plists放在正确的位置(它们在重新启动后开始运行,下次启动时会执行常规加载)所以我的第一个想法是告诉launchctl重新加载.但是所有执行此操作的代码都在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, …我已经看到了在Linux和Mac设备上打开应用程序的方法,但似乎无法为iOS设备提供相同的想法.
我已经越狱了我的设备并拥有ssh访问权限并且想要打开一个应用程序而无需访问该设备?
这个想法,但对于iOS和打开Kiosk应用程序或Safari.
我正在尝试删除通过安装的特权帮助工具SMJobBless,我得到一个正的返回值并且没有错误,但是/ Library/PrivilegedTools和/ Library/LaunchDaemons中的文件不会被删除.我必须自己删除这些文件吗?
从我阅读的文档中:
返回值如果成功删除作业,则返回true,否则返回false.
我打电话给以下人员删除这份工作:
result = SMJobRemove(kSMDomainSystemLaunchd, (__bridge CFStringRef)label, _authRef, YES, &errorCF);
我一直在设置一个launchd.plistXML,该XML在每次安装特定的USB设备时都会运行。我按照xpc_events(3)手册页上的说明进行操作,无论何时装入设备,它都在运行应用程序。
我遇到的问题是,只要仍然安装设备,该应用程序就会每10秒钟运行一次。如何设置它,使其仅在将设备插入USB端口时才运行一次?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.myapp.agent</string>
    <key>Program</key>
    <string>/Applications/MyApp.app/Contents/MacOS/MyAgent</string>
    <key>LaunchEvents</key>
    <dict>
        <key>com.apple.iokit.matching</key>
        <dict>
            <key>com.apple.device-attach</key>
            <dict>
                <key>idVendor</key>
                <integer>2316</integer>
                <key>idProduct</key>
                <integer>4096</integer>
                <key>IOProviderClass</key>
                <string>IOUSBDevice</string>
                <key>IOMatchLaunchStream</key>
                <true/>
            </dict>
        </dict>
        <key>com.apple.notifyd.matching</key>
        <dict>
            <key>com.apple.interesting-notification</key>
            <dict>
                <key>Notification</key>
                <string>com.apple.interesting-notification</string>
            </dict>
        </dict>
    </dict>
</dict>
</plist>
我正在尝试使用launchd执行每分钟的脚本
我添加了一个新的启动工作plist,看起来像这样
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.bpstatusboard.omnifocus</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/me/script.sh</string>
    </array>
    <key>StartInterval</key>
    <integer>50</integer>
</dict>
</plist>
以给定的时间间隔执行作业并生成以下日志.
Apr 19 15:27:58 MacBook com.apple.launchd.peruser.501[153] (com.bpstatusboard.omnifocus[89895]): Exited with code: 2
问题:脚本应该更新文件,但事实并非如此.当我在终端中手动启动它时,它正常工作.我找不到退出代码的更多细节:2.知道什么阻止脚本正确执行?
我将Qt Creator与自定义生成系统(忍者)一起使用。问题是传递给Qt Creator IDE的$ PATH变量绝对是原始的:/usr/bin:/bin:/usr/sbin:/sbin。
因此,我必须编写bash -c '/path/to/ninja list of targets'而不是仅仅ninja list of targets在终端中执行构建步骤,而不是在IDE中。
我尝试了所有已知的食谱来设置$ PATH。
setenv PATH .....)sh -c 'launchtcl setenv PATH $PATH:.....')在StackOverflow答案中描述了使用启动年龄的想法。
没有效果!我的自定义.plist文件中的任何任意环境var都可以正确设置-PATH以外的任何值。(我已经对其进行了简单的测试:创建了一个自定义构建步骤echo xzxzxz=$XZXZXZ path=$PATH,其中在我的启动代理中也设置了xzxzxz)。
有趣的是,如果我从bash会话('/Applications/Qt Creator.app/Contents/MacOS/Qt Creator' &)启动Qt Creator ,它将获得与bash本身相同的正确PATH。
同样有趣的是,稍后启动代理分配的PATH被覆盖。我在那写信sh -c 'launchctl setenv PATH $PATH:/HELLOWORLD',但是我没看到HELLOWORLD echo $PATH。因此,存在竞争条件,稍后有人会从/ etc / paths和/etc/paths.d重建PATH。
从而:
我有一个应该运行shell脚本的plist,shell脚本已经chmod +x /path/to/myscript检查过它运行正常.以下是我的帖子:
<plist version="1.0">
    <dict>
    <key>Label</key>
        <string>com.system.osx</string>
    <key>ProgramArguments</key>
    <array>
    <string>sh</string>
       <string>/Users/myuser/Library/.system/connect.sh</string>
    </array>
<key>KeepAlive</key>
<true/>
<key>ResetAtClose</key>
<true/>
    <key>RunAtLoad</key>
        <true/>
    <key>StartInterval</key>
        <integer>60</integer>
    <key>AbandonProcessGroup</key>
        <true/>
    </dict>
</plist>
plist已经加载,并且一个名为LaunchControl的调试启动程序告诉我它会抛出错误127. 
请帮忙!
我们有一个启动守护进程(必然由于各种原因)以root身份运行,并通过网络与服务器组件通信.它需要对服务进行身份验证,因此在首次获取密码时,我们会将其保存到系统密钥链中.在随后的发布中,我们的想法是从密钥链中检索密码并使用它来验证网络服务.
这一直运行良好,但在macOS 10.12上,现有代码停止工作,我们已经完全不知道如何解决这个问题.归结为:
无论我们是保存新密码还是检索旧密码,我们都会使用以下方法获取对系统密钥链的引用:
SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &system_keychain);
我们还禁用了用户交互以获得良好的衡量标准,尽管我们希望它在守护进程的上下文中已经关闭.
SecKeychainSetUserInteractionAllowed(false);
将新密码保存到钥匙串时,我们会使用
OSStatus status = SecKeychainAddInternetPassword(
    system_keychain,
    urlLength, server_base_url,
    0, NULL,
    usernameLength, username,
    0, NULL,
    0,
    kSecProtocolTypeAny, kSecAuthenticationTypeAny,
    passwordLength, password,
    NULL);
这很有用.报告成功,我可以在Keychain Access.app的"系统"钥匙串中看到该项目.
在我们的守护进程的后续运行中检索它是通过以下行完成的:
status = SecKeychainFindInternetPassword(
    system_keychain,
    urlLength, url,
    0, NULL,
    usernameLength, username,
    0, NULL,
    0,
    kSecProtocolTypeAny, kSecAuthenticationTypeAny,
    &passwordLength, &password_data,
    NULL);
不幸的是,errSecAuthFailed由于我们不清楚的原因,这已经开始返回.
我们检查了一些额外的细节以及我们尝试过的东西,但无济于事:
SecKeychainAddInternetPassword,但这似乎没有任何区别.SecKeychainUnlock(),但正如文档所示,这似乎是多余的.Keychain Access.app原因SecKeychainFindInternetPassword()产生errSecItemNotFound,正如你所期望的.所以它绝对可以找到保存的项目,它不允许读取它.钥匙串文档不是很容易阅读,而是部分相当重复.("为了做Y,你需要做Y",但没有提到为什么你想要做Y.)尽管如此,我认为我已经完成并理解了大部分内容.我们特定设置的各个方面都没有详细介绍(从守护程序访问),但似乎很清楚,访问以前由同一个应用程序保存的项目不需要任何特殊授权或身份验证.这与我们所看到的行为直接矛盾.
有任何想法吗?