3

I am trying to troubleshoot a problem with a bash script that gets called by launchd. Here's a quick summary

  • Calling the script manually by itself works fine with no errors.
  • Within the bash script it calls an AppleScript that posts a notification That AppleScript works fine.
  • The .plist gets loaded and kicks off at the correct interval and calls the bash script. So that works properly
  • The .plist is called from /Library/LaunchDaemons (so it can run regardless if anyone is logged in or not). This means everything is run as root.

The problem occurs within the bash script which calls an AppleScript to post a notification - it just never happens.

#!/bin/bash
# ------------------------------------------------------------------


sleep 11                           
echo "This is a test" > test.txt   
/usr/bin/osascript /Users/allan/Documents/Scripts/AppleScript/notify.scpt "This is a test" "-Test Test Test" "nosound"

exit 0

That's it. A quick summary of what I am doing:

  1. sleep 11 - launchd needs a min. of 10 seconds of program execution time by default. I just put this in here to accommodate launchd
  2. echo "This is a test" - I just write a simple string to a text file to make sure the bash script is getting called. This file gets created with the expected string; this works.
  3. /usr/bin/osascript /Users......blah blah blah... this fails. This is just a simple AppleScript that takes three arguments (body, title, and sound) to provide a notification.

Running by itself or bash script that calls it, it works:

enter image description here

When the bash script is called from launchd it seems to just not work. Can anyone point me in the right direction? What am I missing?

(OS X 10.11.6)


This is the .plist I am using (yes I know it's set for a 45 second interval...I'm testing)

<?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.user.podcastCleanup</string>
    <key>Program</key>
    <string>/Users/allan/Documents/Scripts/Unix/podcastCleanup.sh</string>
    <key>StartInterval</key>
    <integer>45</integer>
    <key>WorkingDirectory</key>
    <string>/Users/allan/Documents</string>
</dict>
</plist>


Following is the notify.scpt AppleScript that is used to generate the notification.

on run argv

    set Message to item 1 of argv
    set Title to item 2 of argv
    set aud to item 3 of argv
    set STitle to "Terminal"
    set Snd to "Blow.aiff"


    if (aud = "sound") then

        display notification Message with title Title subtitle STitle sound name Snd
    else
        display notification Message with title Title subtitle STitle
    end if

end run
  • Please add the scpt and the plist. I'm too lazy to create it! – klanomath Oct 17 '16 at 4:24
  • No problem to get this running in 10.11.6 as ~/Lib/LaunchAgent - even with sleep set to 1 and StartInterval to 10 without any error. Please check the paths in the plist and is the sh executable? – klanomath Oct 17 '16 at 5:32
  • As /Lib/LaunchDaemon the launchd error is "osascript[12982:35171] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data" – klanomath Oct 17 '16 at 5:50
  • @klanomath - Tested as Library/LaunchAgent and it works fine, but I need it to run regardless if I am logged in or not. – Allan Oct 17 '16 at 10:49
3

Graphical User Session Required

The error occurs because the commands in your osascript require a graphical user session. AppleScript requires a graphical user session to work.

The launchd job is running as the root user in a non-graphical user session.

Alternative Approach

In these situations, the typical approach is to split daemons in two parts – one computer wide and another within each graphical user session. A pipe or socket is frequently used to communicate.

Even as root user, there are barriers that can not be crossed in macOS.

  • @Allan to fix it please try to load it from ~/Library/LaunchAgents/ – Mateusz Szlosek Oct 17 '16 at 6:42
  • 1
    This makes sense now that you explain it. Since I need it to run regardless if I am logged in or not, I can't do what @MateuszSzlosek suggested. What I will do is write the "result" to a text file that will be processed by another script that generates notifications when I am logged in...or something to that effect. – Allan Oct 17 '16 at 10:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .