6

I have tried many different variation on this but just can't get it to work.

I have a plist 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.ilium007.handbrake</string>
        <key>ProgramArguments</key>
        <array>
                <string>/bin/bash</string>
                <string>/Users/ilium007/support/scripts/handbrake/handbrake.sh &gt;&gt; /Users/ilium007/support/scripts/handbrake/logs/handbrake_encode.log</string>
                <!--<string>&gt;&gt;</string>-->
                <!--<string>/Users/ilium007/support/scripts/handbrake/logs/handbrake_encode.log</string>-->
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StartInterval</key>
        <integer>60</integer>
</dict>
</plist>

Note the comments in there.

I want to pipe output from the handbrake.sh script to a log file and have tried to do so but keep getting A "no such file" error in system.log on OSX.

Nov  3 18:03:54 macmini com.ilium007.handbrake[15348]: /bin/bash: /Users/ilium007/support/scripts/handbrake/handbrake.sh >> /Users/ilium007/support/scripts/handbrake/logs/handbrake_encode.log: No such file or directory Nov  3 18:03:54 macmini com.apple.launchd.peruser.501[162] (com.ilium007.handbrake[15348]): Exited with code: 127

If I change the plist to the following, it runs but I get no log so I assume it is only running the first argument:

<?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.ilium007.handbrake</string>
        <key>ProgramArguments</key>
        <array>
                <string>/bin/bash</string>
                <string>/Users/ilium007/support/scripts/handbrake/handbrake.sh</string>
                <string>&gt;&gt;</string>
                <string>/Users/ilium007/support/scripts/handbrake/logs/handbrake_encode.log</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StartInterval</key>
        <integer>60</integer>
</dict>
</plist>

The command that I would like to run via launchd is:

/Users/ilium007/support/scripts/handbrake/handbrake.sh >> /Users/ilium007/support/scripts/handbrake/logs/handbrake_encode.log

Nothing ever appears in the log file. But if I run that command from the terminal I get content in the log. Any help would be appreciated.

ilium007
  • 539
  • 3
  • 8
  • 17
  • Belongs on [apple.stackexchange.com](http://apple.stackexchange.com) – lanzz Nov 03 '12 at 08:33
  • @lanzz oh.. apologies. I didn't know there was a different site since I had read other launchd questions here. How do I move it ? – ilium007 Nov 03 '12 at 08:52

3 Answers3

19

>> is a shell operator, not a program argument, and launchd doesn't pass its commands through a shell (unless you force it, as in @Lauri's answer). But launchd does have its own option for redirecting stdout:

<key>StandardOutPath</key>
<string>/Users/ilium007/support/scripts/handbrake/logs/handbrake_encode.log</string>

Note that it automatically appends (equivalent to >>, not >). You can also redirect stderr with the StandardErrorPath key. One thing you cannot do is use ~ (as in ~/support/scripts/handbrake/logs/handbrake_encode.log) -- that, again, is a shell feature that launchd doesn't emulate.

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
  • Much appreciated @gordon-davisson and thanks for the stderr and stdout advice as well. This is the way I have ended up doing it and is working fine now. – ilium007 Nov 04 '12 at 00:14
6

The redirection operators can't be used as arguments. You can either make another script for the pipeline or use bash -c.

<string>bash</string>
<string>-c</string>
<string>bash ~/Desktop/test.sh >> ~/Desktop/test</string>
Lri
  • 26,768
  • 8
  • 84
  • 82
6

The standard out and error keys are very useful, I redirected mine to the first terminal/shell as follows:

<key>StandardOutPath</key>
<string>/dev/ttys000</string>
<key>StandardErrorPath</key>
<string>/dev/ttys000</string>

You can change ttys000 to another number (ttys001..2) if you have multiple terminals. You can find the terminal id by typing in the shell:

tty

This helped me to find out why I was getting console errors in OS X, I needed to have the full path for every command and full paths for directories I was CD'ing to in scripts.

for instance grep is:

/usr/bin/grep

and commands installed by macports use other paths also, like:

/opt/local/bin/lynx

I also tried to chown root:wheel the plist, but this doesn't seem to be necessary, but probably not a bad idea to prevent someone from editing it to whatever...

edit:changed mine back to normal user after I got some permission errors which turned out to be because the script was trying to make files in / without permission, needed to add full paths to output files too, which is weird as it worked the previous day.

D.A. Reyn
  • 81
  • 1
  • 2