【问题标题】:OSX create launchd service for bash script executionOSX 为 bash 脚本执行创建启动服务
【发布时间】:2016-10-17 19:00:55
【问题描述】:

我编写了一个 bash 脚本来持续检查服务。该脚本具有一些功能,并且还调用其他源 bash 文件,并且在手动执行时可以正常工作。该脚本有一个连续的循环语句,例如,

while true; do
{

$path/is_it_running
if [ "$?" == "0" ]; then
{
echo "yes, it is running"
$path/test
if [ "$?" != "0" ]; then
fix_the_issues
fi
}

else 
echo "It is not running!"

fi
sleep 10
}
done

/Library/LaunchDaemons/my.own.service.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>my.own.service</string>
        <key>ProgramArguments</key>
        <array>
            <string>/bin/bash</string>
            <string>/path/to/bash/script</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
         <key>KeepAlive</key>
        <true/>
        <key>StandardOutPath</key>
        <string>/var/log/my-service.log</string>
    </dict>
</plist>

sudo launchctl load -w /Library/LaunchDaemons/my.own.service.plist

/var/log/system.log:

com.apple.xpc.launchd[1] (com.apple.quicklook[80608]): Endpoint has been activated through legacy launch(3) APIs. Please switch to XPC or bootstrap_check_in(): com.apple.quicklook

我面临的问题: 该脚本的运行方式与手动执行时的运行方式不完全相同。我可以说 launchd 触发脚本,因为我可以看到“是的,它正在运行”和“它没有运行!”来自 plist StandardOutPath 日志文件 /var/log/my-service.log 的消息。

任何人都可以在这里帮助我成功地将 bash 脚本作为服务运行吗?与 debian/centos 不同,在 osx 中对我来说看起来很困难。顺便说一句,它是 osx EI Captain 和 Sierra 版本。

【问题讨论】:

  • 尝试在你的脚本#!/bin/bash 的开头放置一个适当的shebang,并从你的参数数组中删除bash。此外,尝试缩进你的 shell 脚本以使其清晰易读并通过shellcheck.net 运行它
  • 脚本文件的顶部有#!/bin/bash,在它调用的所有其他源文件中。我可以删除 plist 参数。如果它正在运行或未完美运行,它会回显,但在服务运行或未运行时不执行某些操作。我一直在测试这个脚本文件,它完全符合我的要求。它在某处使用sudo 提示输入密码,我认为launchd 不会等待回答,因为它以root 身份运行,是吗?。

标签: bash macos startup launchd


【解决方案1】:

以下内容适用于 OSX 10.10 上的 bash 脚本:

<?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>Disabled</key>
    <false/>
    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin</string>
    </dict>
    <key>KeepAlive</key>
    <dict>
         <key>SuccessfulExit</key>
         <false/>
     </dict>
    <key>Label</key>
    <string>SomeNameHere</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>/path/to/bash/script</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

我使用 Lingon 来创建它。您也可以使用免费试用版来解决您当前的问题。

您需要使用版本 4:

需要 macOS 10.11 或更高版本(与 macOS 10.12 完美配合 塞拉利昂)

【讨论】:

  • 哇它现在可以工作了,可能环境变量是关键。但是,launchctl list|stop|start 不起作用,知道为什么吗?
  • 嘿伙计,我去看看
  • 如果我可以启动和停止服务,那会很棒,仍然很棒。这对我帮助很大!。
【解决方案2】:

这是对脚本中 bash 反模式的风格修复。我会将其作为评论发布,但 cmets 不能包含代码格式。

while true; do
#{  no braces necessary here
# note indentation
    # Don't examine $? -- if already does that for you
    if $path/is_it_running; then
    #{ no braces necessary here
    # note indentation
        echo "yes, it is running"
        # Don't examine $? -- if already does that for you
        if $path/test; then
            fix_the_issues
        fi

    #}  No braces necessary       
    else 
        # Note indentation
        echo "It is not running!"
    fi
    sleep 10
#} No braces necessarsy
done

您可能还想访问http://shellcheck.net/ 以自动审查您的脚本。 (虽然它不检查缩进,这纯粹是为了人类的易读性。)

【讨论】:

  • 这出现在审查队列中等待删除,我觉得有点奇怪。我认为这是一个 XY 答案。这似乎是解决他们不知道的 OP 问题的有益尝试。几乎不寻常。
猜你喜欢
  • 2015-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-26
  • 1970-01-01
  • 2021-08-15
  • 2015-10-21
  • 2013-01-19
相关资源
最近更新 更多