Run bash script at login stored in the home folder?

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`

Solution 1:

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, however tilde expansion works in WatchPaths by default.

Solution 2:

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>

Solution 3:

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.