有的,而且在 macOS 上这是"标准正确姿势" 👍
你现在这种需求:
每次开机自动执行
sh /Users/wangjun/Plugin/ja-netfilter-all-main/scripts/install.sh
👉 最佳方案:用 launchd(mac 官方启动机制)
不推荐 crontab、不推荐登录项、不推荐 shell hack。
下面我给你 一步到位、可复制的方案。
✅ 推荐方案:launchd 开机自动执行(最稳)
一、先确认脚本可执行(重要)
chmod +x /Users/wangjun/Plugin/ja-netfilter-all-main/scripts/install.sh
如果脚本里有 #!/bin/bash 或 #!/bin/sh,后面就不用写 sh 了。
二、创建 LaunchAgent(用户级,最常用)
mkdir -p ~/Library/LaunchAgents
新建 plist 文件:
nano ~/Library/LaunchAgents/com.wangjun.ja-netfilter.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.wangjun.ja-netfilter</string>
<key>ProgramArguments</key>
<array>
<string>/bin/sh</string>
<string>/Users/wangjun/Plugin/ja-netfilter-all-main/scripts/install.sh</string>
</array>
<!-- 登录即执行 -->
<key>RunAtLoad</key>
<true/>
<!-- 失败自动重试(可选) -->
<key>KeepAlive</key>
<false/>
<!-- 日志(强烈建议保留) -->
<key>StandardOutPath</key>
<string>/tmp/ja-netfilter.out.log</string>
<key>StandardErrorPath</key>
<string>/tmp/ja-netfilter.err.log</string>
</dict>
</plist>
保存:Ctrl + O → 回车 → Ctrl + X
三、加载并立即生效
launchctl load ~/Library/LaunchAgents/com.wangjun.ja-netfilter.plist
立即测试是否执行:
cat /tmp/ja-netfilter.out.log
cat /tmp/ja-netfilter.err.log
四、验证是否真的生效
launchctl list | grep ja-netfilter
🔁 常用维护命令(记住这几个)
停止
launchctl unload ~/Library/LaunchAgents/com.wangjun.ja-netfilter.plist
重新加载(改脚本后)
launchctl unload ~/Library/LaunchAgents/com.wangjun.ja-netfilter.plist
launchctl load ~/Library/LaunchAgents/com.wangjun.ja-netfilter.plist
⚠️ 常见坑(你很可能会踩)
❌ 1. 脚本里用到了环境变量
launchd 没有 bash/zsh 环境变量
如果脚本里有 JAVA_HOME / PATH,要么:
-
在脚本里写死
-
或在 plist 里加:
<key>EnvironmentVariables</key>
<dict>
<key>JAVA_HOME</key>
<string>/Library/Java/JavaVirtualMachines/xxx.jdk/Contents/Home</string>
</dict>
❌ 2. 脚本需要 sudo?
👉 LaunchAgent 没法 sudo
如果你的 install.sh 里有 root 操作,你要用 LaunchDaemon(系统级),我可以给你那套写法。
🧠 给你一句专业建议
macOS 上:
-
登录即跑 → LaunchAgent
-
开机就跑(root)→ LaunchDaemon
-
❌ 不要 crontab
-
❌ 不要 登录项.app
你现在这个需求,LaunchAgent 是最干净、最不容易炸的方案。
如果你愿意,把 install.sh 内容贴一小段出来
我可以帮你判断:
-
是否需要 root
-
是否需要延迟执行(等网络 / Java)
-
是否应该
KeepAlive=true
这一步你已经走在正确工程路线上了。