如何在不使用 SSH 的情况下远程告诉 Mac 进入睡眠状态?

如何在不使用 SSH 的情况下远程告诉 Mac 进入睡眠状态?

我需要帮助让 Mac 不使用 SSH 进入睡眠状态。几乎任何其他方法都可以接受。

背景故事:产品销售员和项目经理无需询问程序员即可销售产品。程序员现在必须使用只能发送 UDP 和 TCP 字符串/十六进制的产品来打开和关闭 Mac。它确实允许进行痛苦的手动 Telnet 过程,而 SSH 完全不在考虑范围内。我们 100% 不是 MAC 用户。

我们尝试过的事情:

  • homebrew 的 telnetd - 拒绝打开,控制台状态运行 0 秒,10 秒后重新生成。搜索如何调试这个问题已经导致上百个死胡同“它应该可以正常工作!”当它不能正常工作时,这是没用的。
  • Mac 的 NC 命令。虽然我们能够在端口 3000 和 3001 上在我们的控制服务器和 Mac 之间来回打开 udp 会话,但在谷歌搜索并找到解决方案后,发现除了启动命令之外,它几乎无能为力。
  • 我们尝试将 NC 命令放入 bash 脚本中。这很糟糕,似乎在尝试捕获 NC 的实时输出时,它会锁定该行上的脚本,因此永远不会进行解析。我们做了一个非常简单的测试脚本,如下所示。

     output=$(nc -u -l -k 3000; kill$!)
     echo "$output"
    

再次,Mac 新手,Bash 新手。Google 和 Stack Searchboxes 都让我们失望了!我们确实找到了“pmset sleepnow”命令,它可以完成我们想要的功能,所以就是这样。

只是寻找一种简单的方法来接收“睡眠”的 UDP 消息并让 Mac 进入睡眠状态。

答案1

关于nc和脚本。

如果nc你使用类似于我的 Kubuntu 中的那个(它似乎是 OpenBSD 实现),那么-k意味着“保持倾听”,它将使该工具绝不会自动退出。但即使没有-knc使用 UDP 也无法判断通信是否结束,因为 UDP 是无连接的。当收到第一条消息时,nc将固定在远程端的地址和端口上;除非您使用 ,否则它将保持此状态-w

如果你允许nc退出,然后才解析收到的内容,那么就没有监听进程来处理可能的第二次连接尝试。如果任何给定端口上的通信应该使计算机进入睡眠状态:

nc -w 0 -u -l 3000 >/dev/null && echo "Sleep now!"
# replace echo with pmset or whatever

使用-w 0-k允许我接收从不同地址/端口发送的短消息。该工具不会退出,但可以通过管道传输接收到的数据进行分析:

nc -w 0 -k -u -l 3000 | while IFS= read -r line; do
   [ "$line" = sleep ] && echo "Sleep now!"
done
# replace echo with pmset or whatever

对于短 UDP 消息来说可能没问题。一般来说,存在以下几个问题:

  • 猜测以两个或多个数据包的形式传入的消息可能会-w 0过早触发。来自两个源的较长传输可能会交错。为了防止这种情况,您可以:

    • 使用更长的超时时间(例如-w 1)并希望它足够;
    • 使用 TCP,因此nc知道当前连接何时结束(但请注意,如果另一台设备在没有正式终止连接的情况下消失,nc则会等待;因此-w仍然有用;没有-wTCP keepalive 机制最终会终止连接并解除阻塞nc,这可能在大约两个小时后发生);
  • 至少在我的 Kubuntu 中,nc -k它可以同时处理多个连接,也就是说,当它处理第一个连接时,监听似乎没有间隙。来自不同连接的数据仍然按顺序出现在 stdout 中nc,因此只要第一个连接处于活动状态,循环while read …就不会看到来自其他连接的任何内容。单个(恶意?)连接可能会阻止其他(合法?)连接触发所需的操作。

出于这些原因,建议采用分别分析每个连接数据的方法。您可以使用 来执行此操作socat。比较这是我的另一个答案。对于你来说,一个基本的存根可能是:

socat -T 1 UDP-LISTEN:3000,fork SYSTEM:'
   IFS= read -r line && [ "$line" = sleep ] && echo "Sleep now!" >/dev/tty
'
# again, replace echo with pmset or whatever

shell 代码中没有循环。我们从每个传入连接中读取并测试一行。

笔记:

  • socat在我的 Kubuntu 上使用了它。我不太了解 Mac,但是看到这个
  • 根本就没有任何身份验证。
  • IFS= read -r line期望行正确终止,因此连接设备应发送类似sleep\n表示\n换行符 ( LF, 0x0A) 的内容。

答案2

nc答案可能是最好的答案,特别是如果你不熟悉 Mac(但熟悉 Linux)。另一个选择,我过去曾使用过,是编写一个简单的 CGI 脚本(如果你同意在 Mac 上运行 Apache)。每当运行 CGI 时,它都可以在某个目录中创建一个文件(任何地方,这并不重要,只要 Apache/CGI 可以在那里写入)。

然后,单独编写一个launchd代理(类似于其他 Linux 中的服务/守护程序),用于“监听”此目录中的文件。当代理(实际上是代理背后的脚本)检测到文件时,让 Mac 进入睡眠状态!

它更复杂,但我以前用过!出于某种原因(我猜是出于安全原因),您可以直接从 CGI 调用睡眠诱导可执行文件或 AppleScript,因此使用此文件作为信号量是一种不错的解决方法。

相关内容