macOS 10.13下LaunchDaemon脚本无法发送邮件的问题求助
Got it, let's break down why your script works in the foreground but fails when run via LaunchDaemon—this almost always comes down to environment differences between interactive shells and the stripped-down launchd runtime. Here's how to fix it step by step:
1. First, Capture Debug Logs
LaunchDaemon doesn't show output by default, so let's add logging to your plist to see exactly what's breaking. Update your .plist file in /Library/LaunchDaemons to include log paths:
<?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.yourname.vmcheck</string> <!-- Use a unique label --> <key>ProgramArguments</key> <array> <string>/bin/bash</string> <string>/full/path/to/your/script.sh</string> <!-- Always use absolute paths! --> </array> <key>StartInterval</key> <integer>60</integer> <!-- Add logging --> <key>StandardOutPath</key> <string>/var/log/vmcheck_out.log</string> <key>StandardErrorPath</key> <string>/var/log/vmcheck_err.log</string> <key>RunAtLoad</key> <true/> </dict> </plist>
Then reload the daemon and check logs after a minute:
sudo launchctl unload /Library/LaunchDaemons/com.yourname.vmcheck.plist sudo launchctl load /Library/LaunchDaemons/com.yourname.vmcheck.plist cat /var/log/vmcheck_err.log
This will tell you if commands like vmrun or sendmail are missing, or if Postfix is throwing errors.
2. Fix Path & Environment Variables
LaunchDaemon runs with a minimal PATH (usually just /bin:/usr/bin), which means commands installed in non-standard locations (like vmrun inside VMware Fusion's bundle) won't be found. Fix this two ways:
Option A: Use Absolute Paths in Your Script
Update every command in your script to use full paths:
#!/bin/bash # Full path to vmrun VM_RUN="/Applications/VMware Fusion.app/Contents/Library/vmrun" # Full path to your VM's .vmx file VM_PATH="/Users/yourusername/Documents/Virtual Machines/Ubuntu/Ubuntu.vmx" # Check if VM is running if ! "$VM_RUN" list | grep -q "$VM_PATH"; then # Use absolute path to sendmail /usr/sbin/sendmail -t <<EOF To: your-alert-email@example.com From: vm-monitor@your-mac.local Subject: Ubuntu VM is Down! Your VMware Fusion Ubuntu VM has stopped running. Please log in to restart it. EOF fi
Option B: Explicitly Set PATH in the Plist
Add an EnvironmentVariables section to your .plist to expand the available paths:
<key>EnvironmentVariables</key> <dict> <key>PATH</key> <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Library</string> </dict>
3. Verify Postfix & Permissions
Since your script works in the foreground, Postfix is configured correctly for your user—but LaunchDaemon runs as root by default. Make sure:
- Postfix's system-wide configuration (in
/etc/postfix/main.cf) includes your relay settings, not just user-specific configs. - The
rootuser has permission to send mail through your relay. If your relay requires SASL auth, ensure the credentials are stored in a system-wide Postfix config (not just~/.postfixrcfor your user).
4. Validate Plist Permissions
LaunchDaemon requires strict file permissions for plists:
sudo chown root:wheel /Library/LaunchDaemons/com.yourname.vmcheck.plist sudo chmod 644 /Library/LaunchDaemons/com.yourname.vmcheck.plist
Incorrect permissions will cause launchd to ignore the plist entirely.
Final Test
After making these changes, reload the daemon and wait a minute. Check the logs again—if everything works, you should see no errors in vmcheck_err.log, and get your alert email when the VM is down.
内容的提问来源于stack exchange,提问作者stubert

