How to start with launchd a bash script that calls fswatch with `&`

bashcommand linelaunchdterminal

Manually it works

I have a bash script called git-watch.sh (gist link) that calls fswatch in a loop like this:

while read -r line; do
  {
    fswatch -r "$line" | grep --line-buffered -v '.git' | xargs -n1 -I{} git-commit-unattended.sh "$line";
  } &
done

(Note the ampersand. I had to use it because fswatch blocks waiting for change, so the while wouldn't get past the first iteration otherwise. It could be interfering with launchd though, not sure.)

It works fine if I call it from the command line passing it a file, like

git-watch.sh < /Users/kbdluv/Dropbox/dotfiles/git-watch-paths.txt

Running ps aux | grep fswatch yields:

kbdluv           9629   0.0  0.0  4278008    920 s001  S+    5:46PM   0:00.00 grep fswatch
kbdluv           9415   0.0  0.0  4299876   4912 s001  S     5:37PM   0:00.01 fswatch -r /Users/kbdluv/Dropbox/org
kbdluv           9414   0.0  0.0  4315736   4944 s001  S     5:37PM   0:00.01 fswatch -r /Users/kbdluv/Dropbox/dotfiles

Which is what we want.


Launchd doesn't

But now I want it to start automatically on login, and I haven't been able to get launchd to cooperate.

Here's my com.user.gitWatchMyPathsOnLogin.plist so far:

<?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.user.gitWatchMyPathsOnLogin</string>
   <key>ProgramArguments</key>
   <array><string>/Users/kbdluv/Dropbox/dotfiles/scripts/git-watch-my-paths-on-login.sh</string></array>
   <key>RunAtLoad</key>
   <true/>
   <key>StandardOutPath</key>
   <string>/tmp/com.user.gitWatchMyPathsOnLogin.out</string>
   <key>StandardErrorPath</key>
   <string>/tmp/com.user.gitWatchMyPathsOnLogin.err</string>
</dict>
</plist>

It loads without error. It starts without outputting anything to stderr or stdout either, but here's what ps aux | grep fswatch gives me:

kbdluv          11550   0.0  0.0  4267768    888 s001  S+    7:56PM   0:00.00 grep fswatch
kbdluv          11545   0.0  0.0  4298088   4932   ??  S     7:56PM   0:00.01 fswatch -r /Users/kbdluv/Dropbox/org

It runs fswatch only with the last line in the git-watch-paths.txt file. (The fswatch for dotfiles is missing.)

And it doesn't auto-commit when a change happens, so I guess the parts fswatch is being piped to aren't getting called.


What am I doing wrong, or how could I debug this further when launchd isn't throwing any error or outputting anything?

Best Answer

What happens if you amend git-watch.sh to use the "wait" command to wait on the background processes?

while read -r line; do
  {
    fswatch -r "$line" | grep --line-buffered -v '.git' | xargs -n1 -I{} git-commit-unattended.sh "$line";
  } &
done

wait