2

I'm been trying to write a plist file on which when I return from sleep mode, I always want to make my Mac volume to the minimum amount. However, it looks like the following plist doesn't work, with an error: 1:1: syntax error: Expected string but found end of script. (-2741)

<?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>KeepAlive</key>
        <false/>
        <key>Label</key>
        <string>my.plist</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/bin/osascript</string>
            <string>-e</string>
            <string>"</string>
            <string>set</string>
            <string>volume</string>
            <string>output</string>
            <string>volume</string>
            <string>0</string>
            <string>"</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
</plist>

Also, when the following is not working:

<?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>KeepAlive</key>
        <false/>
        <key>Label</key>
        <string>my.plist</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/bin/osascript</string>
            <string>-e</string>
            <string>"set volume output volume 0"</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
</plist>

The osascript command functions well if I execute it from within Terminal, so I think it's due to how I set my arguments list to the plist.

So is it feasible to take the string argument like "~" in launchd? Or is there some other things that I'm missing here?

I suspect that it might be better to write the osascript command in shell script, and load the shell script to enable the Mac's volume to minimize... but is it the correct approach?

I use OS X Mavericks 10.9.2.

2 Answers 2

2

The second launchd job ticket format is almost correct. Only a set of quotes need removing.

Quotes

The quotes are no longer needed in the second launchd job ticket, so change:

<string>"set volume output volume 0"</string>

…to…

<string>set volume output volume 0</string>

Grouping Arguments

In this case, the quotes grouped the set of arguments for osascript to see as one item. Thus osascript gets two arguments, the flag -e and the script. This meets the requirements from the osascript manual.

When called through Terminal.app and thus through the shell, the quotes are needed to perform the grouping. When osascript gets the arguments, the shell has removed the quotes.

Without quotes, spaces subdivide each item passed via the shell.

When called through a launchd job ticket, the grouping is intrinsic within the array passed as ProgramArguments. In your first ticket, the array contained nine items and in the second ticket, the array contained three.

LaunchAgent

Be sure to add this launchd job as a ~/Library/LaunchAgents as osascript requires an active user with a graphical session.

This approach approximates what I do with Power Manager in How to Set the Volume When Logging In.

4
  • Thanks. How can I tell which arguments can be specified in one line (like this case) and which cannot (hence lots of <string></string>)?
    – Blaszard
    Commented Apr 27, 2014 at 7:34
  • I have expanded the answer to discuss a little about quotes and grouping. Hope it helps. Commented Apr 27, 2014 at 8:18
  • Thank you for the excellent follow-up. Then for example, if I want to execute mysql -uroot -e "sql_statement", then the devision is mysql, -u, root, -e, and sql_statement (without quote), right?
    – Blaszard
    Commented Apr 27, 2014 at 8:29
  • Yes, I think you are correct but I am not certain. It seems the shell may perform an extra step in this example and actively split the -u from root. This answer shreds more light on the subject, stackoverflow.com/questions/3178181/… Commented Apr 27, 2014 at 8:50
2

The second plist should work if you remove the extra quotes, but it only runs the command at login and not after waking up from sleep.

You can use sleepwatcher to run a command after waking up from sleep. Run sudo -v and paste lines like this in a shell:

curl http://www.bernhard-baehr.de/sleepwatcher_2.2.tgz|tar -x
sudo mkdir -p /usr/local/sbin /usr/local/share/man/man8
sudo cp sleepwatcher_2.2/sleepwatcher /usr/local/sbin
sudo cp sleepwatcher_2.2/sleepwatcher.8 /usr/local/share/man/man8
cp sleepwatcher_2.2/config/de.bernhard-baehr.sleepwatcher-20compatibility-localuser.plist ~/Library/LaunchAgents
launchctl load ~/Library/LaunchAgents/de.bernhard-baehr.sleepwatcher-20compatibility-localuser.plist
echo $'#!/bin/sh\nosascript -e "set volume output volume 0"'>~/.sleep
chmod +x ~/.sleep

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .