![OSX Mavericks:如何使 Web 服务器在启动时启动并监听端口 80,而无需以 root 身份运行 Web 服务器?](https://linux22.com/image/1400738/OSX%20Mavericks%EF%BC%9A%E5%A6%82%E4%BD%95%E4%BD%BF%20Web%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%9C%A8%E5%90%AF%E5%8A%A8%E6%97%B6%E5%90%AF%E5%8A%A8%E5%B9%B6%E7%9B%91%E5%90%AC%E7%AB%AF%E5%8F%A3%2080%EF%BC%8C%E8%80%8C%E6%97%A0%E9%9C%80%E4%BB%A5%20root%20%E8%BA%AB%E4%BB%BD%E8%BF%90%E8%A1%8C%20Web%20%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%9F.png)
[launchd] 消除了以 root 身份运行守护进程的主要原因。因为 launchd 以 root 身份运行, 它可以创建低编号的 TCP/IP 侦听套接字并将它们交给守护进程。
那很好...但是怎么做呢?
我想要执行以下操作:
- 在启动时启动 Nginx 网络服务器
- 让它监听 80 端口
_www
以用户身份运行
这正是上述文档所讨论的情况。但我还没有找到一种不给出错误消息的方法bind() to 0.0.0.0:80 failed (13: Permission denied)
。
这是我的 .plist 文件/Systems/Library/LaunchDemons/homebrew.mxcl.nginx.plist
:
<!--
Adapted from the .plist file provided as part of
the Mac Homebrew distribution of nginx.
-->
<?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>
<!--
Here's the problem!!
<key>Username</key>
<string>_www</string>
-->
<!--
I thought that Sock(et) declarations would be
the way to tell launchd to hand off a port to the
daemon. So I added these lines, but they don't
appear to make any difference at all.
-->
<key>SockServiceName</key>
<string>http</string>
<key>SockType</key>
<string>stream</string>
<key>SockFamily</key>
<string>IP4</string>
<key>Label</key>
<string>homebrew.mxcl.nginx</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
<key>StandardOutputPath</key>
<string>/var/log/nginx.log</string>
<key>StandardErrorPath</key>
<string>/var/log/nginx.log</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/opt/nginx/bin/nginx</string>
</array>
<key>WorkingDirectory</key>
<string>/usr/local</string>
</dict>
</plist>
如您所见,Username: _www
被注释掉了。因此,当我以 root 身份运行 launchd 时,nginx 以 root 身份运行,一切正常。但是当我包含声明时Username: _www
,nginx 失败并在日志文件中留下此错误消息:
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
我错过了什么?
答案1
守护进程需要“获取”由 launchd 绑定的套接字(例如launch_data_get_fd
:) - 它需要能够识别 launchd 并在内部实现一些逻辑。据我所知,nginx 并非如此,因此我建议使用以下选项之一:
- 将 nginx 端口调整为 > 1024,然后设置防火墙以将来自/到端口 80 的流量重定向到/从 nginx 端口;
- 让 launchd 以 root 身份运行 nginx,然后通过更改
user
其配置文件中的指令让 nginx 放弃其权限;