为什么 bash 脚本中的“mail”可以在命令行中正常运行,但在 launchd 运行时却不能正常运行?

为什么 bash 脚本中的“mail”可以在命令行中正常运行,但在 launchd 运行时却不能正常运行?

这是在运行 Big Sur 的 iMac 上进行的。 (我在 AskDifferent 上问过,但没有人知道答案。)

该脚本设置为由 launchd 每天运行一次,以从 Raspberry Pi 上运行的 NUT(网络 UPS 工具)服务器获取电池数据:

#!/bin/bash
# Shell script to query upsmon regarding ups battery status
log=/Users/mnewman/ups/ups.log
email="[email protected]"
echo `date` "UPS Check">> $log
# get UPS data from Raspsky
bat=`/usr/local/bin/upsc apcups@raspsky | \
grep -E 'battery.charge:|input.voltage:'`
# write USB data to the log
echo $bat >> $log
# send an email
echo "$bat" | /usr/bin/mail -s "UPS Status" $email
exit 0

该脚本从命令行运行良好。它从 launchd 运行,但电子邮件行除外,该行默默地失败 - 控制台日志中没有任何内容,stderr 中也没有任何内容。电子邮件只是没有发送出去。

但是,如果我在详细模式下运行邮件命令:

echo "$bat" | /usr/bin/mail -v -s "UPS Status" $email

它运行良好。

或者,如果我在电子邮件行后添加另一个命令:

curl -sS https://api.prowlapp.com/publicapi/add  \
        -F apikey=$apikey -F application=$(hostname) -F event="UPS"  \
        -F description="$bat"

它运行良好。

谁能解释一下这里发生了什么?

答案1

我在其他地方学到了这个。事实证明:

<key>AbandonProcessGroup</key><true/>

必须添加到 launchd plist 文件中。当作业完成时,launchd 会终止与该作业具有相同进程组 ID 的任何剩余进程。此设置禁用该行为。问题是邮件启动了一个子进程来发送邮件,当脚本执行完毕时,该子进程可能尚未完成。如果 launchd 终止该子进程,则不会发送邮件。这就是我在 OP 中描述的情况所发生的情况。我的猜测是,通过在详细模式下运行邮件或在邮件行后添加其他命令,可以使脚本保持足够长的活动时间,以便邮件完成发送电子邮件。

相关内容