美文网首页
macOS Launchd 启动任务

macOS Launchd 启动任务

作者: 游城十代2dai | 来源:发表于2023-11-30 18:14 被阅读0次

    macOS 通过启动硬盘指定目录下的配置文件,来完成启动任务。这些文件为plist,本质上是XML。

    0x00 Launchd 目录配置

    Mac下Launchd的plist文件放置的目录有

    由用户自己定义的任务项
    ~/Library/LaunchAgents        
              
    由管理员为用户定义的任务项
    /Library/LaunchAgents                    
    
    由管理员定义的守护进程任务项
    /Library/LaunchDaemons             
    
    由 macOS 为用户定义的任务项
    /System/Library/LaunchAgents 
          
    由 macOS 定义的守护进程任务项
    /System/Library/LaunchDaemons 
    

    其中 LaunchDaemons 和 LaunchAgents 的区别是什么?

    • LaunchDaemons 是用户未登陆前就启动的服务(守护进程)
    • LaunchAgents 是用户登陆后启动的服务(守护进程)

    0x01 Launchd Plist 配置

    标签 必填 说明
    Label 标识符,用来表示该任务的唯一性
    Program 程序名称,用来说明运行哪个程序、脚本
    ProgramArguments 同上,与Program二选一或一起使用,只是可以运行多个程序、可带参数
    WatchPaths 监控路径,当路径文件有变化是运行程序,也是数组
    RunAtLoad 是否在加载的同时启动
    StartCalendarInterval 运行的时间,单个时间点使用dict,多个时间点使用 array -> dict
    StartInterval 时间间隔,与StartCalendarInterval使用其一,单位为秒
    StandardInPath、StandardOutPath、StandardErrorPath 标准的输入输出错误文件,这里建议不要使用.log作为后缀,会打不开里面的信息

    两种指定要执行命令的方法:

    使用 Program 和 ProgramArguments

    • Program, 运行命令或要执行文件路径
    • ProgramArguments, 执行时传入参数

    只使用 ProgramArguments

    • ProgramArguments 的每个参数为要执行的命令或文件路径,其它参数为传入参数

    两种设置执行时间的方法:

    • StartCalendarInterval 使用元素Minute, Hour, Day, Month, Weekday指定执行时间,如:
    <!-- 每天的9:30执行 -->
    <key>StartCalendarInterval</key>
    <dict>
      <key>Minute</key>
      <integer>30</integer>
      <key>Hour</key>
      <integer>9</integer>
    </dict>
    
    • StartInterval 设置执行的时间间隔,单位为秒
    <!-- 每小时执行一次 -->
    <key>StartInterval</key>
    <integer>3600</integer>
    

    0x02 Launchd 定时任务

    编写我的 shell 脚本文件

    功能是在 macOS 开机后自动执行下面的脚本, 开启内网穿透的功能, 可以忽略我的脚本内容, 替换成你想用的脚本

    # launch.sh
    #! /bin/bash
    
    export ZWY_HOME=/Users/mb
    export ZWY_DIR=$ZWY_HOME/ZwyShell
    export ZWY_DIR_FeiGeNAT=$ZWY_HOME/ZwyShell/darwin_amd64_client
    export PATH=$PATH:$ZWY_DIR:$ZWY_DIR_FeiGeNAT
    
    LOG_PATH=$ZWY_DIR/launch/launch.log
    
    echo "====start zwy launch====" >> $LOG_PATH
    
    echo $(date +"%Y-%m-%d %H:%M:%S") >> $LOG_PATH
    echo "npc is in "`which npc` >> $LOG_PATH
    
    npc -server=nps.xxxx.press:8024 -vkey=zwy -type=tcp > $ZWY_DIR_FeiGeNAT/npc_home.log
    

    注意:
    可以使用 chmod a+x launch.sh 给权限变成可执行文件, 也可以用 bash 命令调用

    编写 Plist 文件

    ~/Downloads 下面创建一个 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.zwy.home</string>
        <key>ProgramArguments</key>
        <array>
            <string>bash</string>
            <string>/Users/mb/ZwyShell/launch/launch.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>Version</key>
        <string>3</string>
    </dict>
    </plist>
    

    可以用 plutil -lint com.zwy.home.plist 来验证 Plist 格式是否正确

    加载命令

    launchctl 是一个统一的服务管理框架,启动、停止和管理守护进程、应用程序、进程和脚本

    
    # 加载任务, -w选项会将plist文件中无效的key覆盖掉,建议加上
    launchctl load -w com.zwy.home.plist
    launchctl start com.zwy.home
    
    # 删除任务
    launchctl stop com.zwy.home.plist
    launchctl unload -w com.zwy.home
    
    # 查看任务列表, 使用 grep '任务部分名字' 过滤
    launchctl list | grep 'com.zwy.home.plist'
    

    经验

    如果执行 launchctl load 命令出现 com.zwy.home.plist: Path had bad ownership/permissions,需要为 plist 文件赋予600 权限或者 root 权限, 都可以尝试一下:

    sudo chmod 600 path/com.zwy.home.plist
    
    sudo chown root:wheel path/com.zwy.home.plist
    

    执行 launchctl list 查看到你的执行结果, 其他错误可以用 launchctl error <insert numerical error code here>来查看具体错误:

    $ launchctl list | grep 'com.zwy.home'
    -    78    com.zwy.home # 错误结果
    -    0      com.zwy.home # 正确结果
    

    执行 launchctl list 具体描述如下:

    1230    -   com.apple.speech.speechsynthesisd
    353     -   com.apple.security.cloudkeychainproxy3
    255     -   com.apple.secd
    -       0   com.apple.sbd
    
    第一列表示进程号,如果有在结果中罗列,但没有数字而只是一个横线,标志虽然已经loaded, 但没有运行
    第二列是上次退出的状态号(the last exit code), 0表示成功,正数表示错误退出,负数表示收到信号后退出
    

    如果 shell脚本输出如果有中文,中文部分乱码,则需要在shell脚本中指定编码:

    #!/bin/bash
    
    LANG=en_US.UTF-8
    export LANG
    
    echo "你好贾维斯"
    

    相关文章

      网友评论

          本文标题:macOS Launchd 启动任务

          本文链接:https://www.haomeiwen.com/subject/uomqgdtx.html