launchd - how to keep script running in the background

I have a simple script to upload the file to dropbox whenever it changes. I wanted to run it at system startup and keep it in a background to let the script watch the file.

I've created a plist, however it runs the script and exits with code 0.

plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.launchd.dropbox_uploader</string>
    <key>ProgramArguments</key>
    <array>
    	<string>sh</string>
    	<string>-c</string>
    	<string>~/dropbox-uploader.sh; wait</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

(doesn't work neither with, nor without wait in the command)

script (it works fine and doesn't exit when run in command line)

#!/bin/sh

fswatch -o ~/file.txt | xargs -n1 -I{} curl -X POST https://content.dropboxapi.com/2/files/upload \
    --header 'Authorization: Bearer XXXXX' \
    --header 'Content-Type: application/octet-stream' \
    --header 'Dropbox-API-Arg: {"path":"/backup/file.txt","strict_conflict":false,"mode":{".tag":"overwrite"}}' \
    --data-binary @'~/file.txt'

launchtl list output

 ~> launchctl list | grep com.example                                                                                                                       (base) 
-	0	com.example.launchd.dropbox_uploader

How to achieve my goal to have it run in the background? I'm not sure if there's an issue with my plist or script.

Answers

Enabling the file output as Gordon mentioned in his comment helped to find the reason.

The issue was:

/Users/me/dropbox-uploader.sh: line 3: fswatch: command not found

So changing fswatch to the absolut fswatch bin path /usr/local/bin/fswatch solved the problem. I've also replaced ~/ with the absolute path in the plist and made sure that script is executable.

Final script:

#!/bin/sh

/usr/local/bin/fswatch -o ~/file.txt | xargs -n1 -I{} curl -X POST https://content.dropboxapi.com/2/files/upload \
    --header 'Authorization: Bearer XXXX' \
    --header 'Content-Type: application/octet-stream' \
    --header 'Dropbox-API-Arg: {"path":"/backup/file.txt","strict_conflict":false,"mode":{".tag":"overwrite"}}' \
    --data-binary @'~/file.txt'

plist with file output enabled

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.launchd.dropbox_uploader</string>
    <key>ProgramArguments</key>
    <array>
    	<string>/Users/me/dropbox-uploader.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/Users/me//dropbox.out</string>
    <key>StandardErrorPath</key>
    <string>/Users/me/dropbox.err</string>
</dict>
</plist>
Posted on by akn

Edit crontab file with crontab -e and add the following to that file:

@reboot /path/to/job

This will run your job every time your system reboots and keep it running in the background.

Posted on by N01