Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

When I try to load a LaunchAgent plist from launchctl I can't find out how to run a script in the home directory.

My code is:

<?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>ProgramArguments</key>
    <array>
        <string>bash</string>
        <string>~/script.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>Label</key>
    <string>com.tyilo.test</string>
</dict>
</plist>

I have tried both with and without bash and also replacing ~ with $HOME. I have also tried using bash -c without it working.

The error code is: com.tyilo.test: bash: ~/script.sh: No such file or directory

share|improve this question
    
Try putting the full path e.g. /Users/name/script.sh (Also I would make the script executable and with first line #!/bin/bash and run it directly) –  Mark Jan 13 '12 at 0:36
    
I can't use the full path as it is to be used on multiple accounts and computers. –  Tyilo Jan 13 '12 at 0:47
    
If it is to be used my multiple accounts then you should put it in /usr/local/bin/ instead of making multiple copies of it in each user's $HOME. It would be helpful to know what you are trying to accomplish with this script. It sounds like a job for a LoginHook, IMO. –  TJ Luoma Jan 13 '12 at 17:14

6 Answers 6

up vote 9 down vote accepted

EnableGlobbing enables tilde and wildcard expansion for ProgramArguments:

<key>EnableGlobbing</key>
<true/>
<key>ProgramArguments</key>
<array>
    <string>say</string>
    <string>~/*</string>
</array>

It doesn't affect Program or WatchPaths, but tilde expansion works in WatchPaths by default.

share|improve this answer
    
This is way better way of doing this. Is there a place where you can view the documentation for the keys in a LaunchAgent plist? –  Tyilo Mar 8 '13 at 7:01
    
man launchd.plist. Or see this blog post or my website. –  ؘؘؘؘ Mar 8 '13 at 7:26
    
Thanks! That really helped me. –  binarybob Jul 11 '13 at 19:51
1  
This helped me too. Tried in the following Mac OS X Versions: 10.7, 10.8, and 10.9. –  Dj S Mar 24 at 7:34

EnableGlobbing doesn't work on OS X Yosemite 10.10. It has been deprecated (ref).

You can see in logs The EnableGlobbing key is no longer respected. Please remove it. (from /var/log/system.log)

The problem is that launchd cwd (current working directory) is /, so you can't use ./ like some people said.

To run a script from your home the simple way is to use (bash|zsh|sh) -c. option. This way you will have the ability to use the tilde ~ or the $HOME variable.

<?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>org.your.stuff</string>
    <key>ProgramArguments</key>
    <array>
      <!-- here is the important thing -->
      <string>zsh</string>
      <string>-c</string>
      <string>~/you/script/in/your/home</string>
    </array>

    <!-- code below is just for the example -->
    <!-- Keep running... -->
    <key>KeepAlive</key>
    <true />
    <!-- ...every day. In sec, 60*60*24 = every day -->
    <key>ThrottleInterval</key>
    <integer>86400</integer>
  </dict>
</plist>
share|improve this answer

The most reliable I found of doing this was by using sh and the HOME enviroment variable:

<?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>ProgramArguments</key>
    <array>
        <string>sh</string>
        <string>-c</string>
        <string>"$HOME/script.sh"</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>Label</key>
    <string>com.tyilo.test</string>
</dict>
</plist>

Note: the quotes are required.

share|improve this answer

If your script is a user agent (and thus located in the library of the Home folder), launchd's current working directory is the Home folder. UNIX refers to the home directory with a period in the path.

So basically, use ./script.sh instead of ~/script.sh. ;-)

share|improve this answer
    
Nope, the working directory of launchd is actually /, not '~'. –  Tyilo Mar 7 '13 at 20:05
    
@Tyilo I'm not sure what you mean. If you mean "launchd's working directory is the root, in all cases—even in user mode", please provide a reference. If you mean "launchd uses a slash instead of a tilde", read my post again. By the way, I have several scripts scheduled in launchd and they follow the behaviour I describe. ;-) –  Randy Marsh Mar 7 '13 at 23:41
    
@RandyMarch I made a launch agent in ~/Library/LaunchAgents with the arguments: sh, -c, echo $HOME > /Users/Tyilo/launchd_home.txt. When ran the file /Users/Tyilo/launchd_home.txt contained /, not /Users/Tyilo. –  Tyilo Mar 7 '13 at 23:47

Is it executable?

chmod 700 ~/script.sh

in Terminal. Also, I would not use $HOME or ~ but rather the actual path to the file.

<?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.tyilo.test</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/script.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
share|improve this answer
    
What's the reason for the downvote? –  TJ Luoma Jan 30 '13 at 15:04

It would be helpful to know why the script needs to be run from the user's home directory. If you need the user's shortname for the script you can get it by assigning it to a variable as in

user=`whoami`

Then use $user in the script.

I would really put the script somewhere other than a home directory, then it's accessible by other users on the same computer. You could use the Shared directory or put the script in /Library/Scripts/

You will have to use the full path for the launchd plist. Also, in your launchd plist you won't need to specify <string>bash</string> as you should have the shebang in the script and it should be executable.

share|improve this answer
    
Specifying bash as the actually command to execute is a good fallback with no real detriment. If he doesn't have the shebang, or forgets to make the script executable (o=rwx), then bash will still invoke / execute the script. –  Jason Salaz Jan 13 '12 at 17:13
    
There should already be a variable for the username, such as $USER or $LOGNAME. Also, the usual location for shared Unix scripts would be /usr/local/bin/ (not that you couldn't put them elsewhere, but /usr/local/bin/ will most likely already be in your $PATH). –  TJ Luoma Jan 13 '12 at 17:23
    
Using whoami is just another method for getting at the same info as $USER or $LOGNAME. I suggested the locations above as I didn't want to presume anything of the questioner. Also, before trying to make the launchd plist work, the script actually needs to be able to run from the CLI. –  afragen Jan 13 '12 at 17:34

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.