Posted on 08-11-2015 06:35 AM
This post provided a way for us to launch stuff as the console user in 10.10 and older versions. However I am noticing that its not working quite as good on 10.11. Has anybody been playing with running stuff as the user on the new OS during setup or pushing updates out?
Posted on 08-11-2015 06:51 AM
Hmm. I haven't had the time to really play with 10.11 much yet. Have you also tried the python method posted by Jacob on that thread? Or is that actually what you were referring to up above? I seriously hope our ability to run things as the logged in user will not be completely shut down in 10.11 or that's going to put a real damper on stuff.
Maybe time to upvote this FR some more to see if JAMF can assist with this.
Posted on 08-12-2015 02:08 AM
This won't work in 10.11. You'll need to change the way you do this. Try this process:
1) Start with a standard simple script, eg.
#!/bin/bash
/Applications/terminal-notifier.app/Contents/MacOS/terminal-notifier -message message -title title
exit 0
Create a LaunchAgent plist that points to this script and runs at load:
<?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.mydomain.test</string>
<key>Program</key>
<string>/[pathtoscript]/script.sh</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
2) As root, run the following:
#!/bin/bash
current_user=`stat -f%u /dev/console`
launchctl bootstrap gui/$current_user /Library/LaunchAgents/com.mydomain.test.plist
exit 0
3) To rerun the daemon run:
#!/bin/bash
current_user=`stat -f%u /dev/console`
launchctl kickstart gui/$current_user/com.mydomain.test
exit 0
Notice, that when you kickstart the process you refer to the label not the file.
Of course, you don't want a million different plists per message. You could have a preference plist that contains flags for messages that you read from the original script and based on reply, use a 'case' statement to provide the relevant message. Just remember, as it is set to RunAtLoad, then it will run at first login, so you'll want a reset: perhaps at logout, check process time of loginwindow, etc and less than x default message or no message.
Posted on 08-12-2015 07:18 AM
@sean That seems like a good process. Its reminiscent of something I had put together specifically for calling terminal-notifier some time back, before I found out how to use launchctl bsexec. So we may need to revisit this process once the Captain cometh.
The process I was using looked like this.
Have a LaunchAgent in /Library/LaunchAgents/ that had a WatchPath of a local script file. The script file was initially an empty file and the LaunchAgent did not have the RunAtLoad key enabled. It only ran when the watched file was modified.
A separate script run from Casper would write out my actual script into the WatchPath'ed script file. IOW, I echoed the contents of my terminal-notifier script, complete with variables being pulled down from Casper's parameter assignments, into the script file. As soon as the LaunchAgent saw the change it would fire and run the script, displaying the message. Included in the actual script contents was a final line (after a couple of seconds pause) that would empty the script again by doing echo "" > /path/to/script.sh
So, after it created and ran the script, it would wait for it to run, then empty the contents again so it couldn't be called by accident later. This actually worked nicely, but as it involved needing a LaunchAgent deployed to every Mac and for said Agent to remain active, I ended up tabling it in favor of the launchctl bsexec method.
I may brush off this process and test it against 10.11 to see how it fares. I can't see why it would not work. Its using a standard LaunchAgent process to run the script as the logged in user.
Posted on 08-12-2015 08:43 AM
I will write a test up today and see if it works thanks.
Posted on 08-12-2015 10:21 AM
@sean thank you, that works great. Here is a perl sub-routine to do this all in line and only once... in case anybody is interested.
# runs a command as the console user
# in: command
# out: $rc
sub runAsConsoleUser {
my $consoleuser = getConsoleUser();
my $uid = getpwnam($consoleuser);
my $command = shift;
(my $name = $command) =~ s#.*/##;
$name =~ s#s##g;
my $la = "/Library/LaunchAgents/com.hpe.temp$name.plist";
my $rc;
if ((defined $consoleuser) && (defined $command)) {
syslog('notice', "Running %s as uid %d on console", $command, $uid);
print "opening $la
";
open LA, ">$la" or die "$progname: launch agent: $!
";
print LA "<?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.hpe.temp$name</string>
<key>Program</key>
<string>$command</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>";
close LA;
$rc = system("launchctl bootstrap gui/$uid "$la"");
syslog('notice', "return code from process %s is %d", $command, $rc);
if ($rc) {
syslog('notice', "return code from bootstrap %d, trying kickstart", $rc);
$rc = system("launchctl kickstart gui/$uid/com.hpe.temp$name");
}
unlink $la;
return $rc;
}
else {
syslog('notice', "Something Not defined in properly cannot run as user");
}
}
Posted on 08-12-2015 12:41 PM
Yeah, thought about a WatchPath to, just depends on individual application.
Of course, the script itself could deny a run.
Eg.
#!/bin/bash
defaults read /Library/Preferences/com.mycompnay.terminal-notifier ShouldIRun
if TRUE.....
run stuff
defaults write /Library/Preferences/com.mycompnay.terminal-notifier ShouldIRun -bool FLASE
fi
exit 0
Example plist below. Run trigger script that re-runs the LaunchAgent and sets the MessageType, e.g.
/[pathtoscript]/script.sh ASUSMessage
#!/bin/bash
current_user=`stat -f%u /dev/console`
the_message_type="$1"
defaults write /Library/Preferences/com.mycompnay.terminal-notifier MessageType $the_message_type
launchctl kickstart gui/$current_user/com.mydomain.test
exit 0
Then the script in the LaunchAgent reads the MessageType, reads the relevant string and then applies that to the '-message' option of terminal notifier, e.g..
#!/bin/bash
run_check=`defaults read /Library/Preferences/com.mycompnay.terminal-notifier ShouldIRun`
if [ $run_check = 1 ]
then
my_message_type=`defaults read /Library/Preferences/com.mycompnay.terminal-notifier MessageType`
my_message=`defaults read /Library/Preferences/com.mycompnay.terminal-notifier $my_message_type`
/Applications/terminal-notifier.app/Contents/MacOS/terminal-notifier -message "$my_message" -title "Company Message"
defaults write /Library/Preferences/com.mycompnay.terminal-notifier ShouldIRun -bool FLASE
fi
exit 0
# cat /Library/Preferences/com.mycompnay.terminal-notifier.plist
<?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>MessageType</key>
<string>ASUSMessage</string>
<key>ASUSMessage</key>
<string>Software updates ready</string>
<key>PasswordExpiry</key>
<string>Please change your password</string>
<key>ShouldIRun</key>
<true/>
</dict>
</plist>
RunAtLoad can stay as yes and at login nothing will happen, unless you set the 'ShouldIRun' flag to TRUE. This way you can trigger a message event at the login window that won't activate until the user logs in, whilst a WatchPath wouldn't provide a message whilst at login window (which may of course be your desired effect).
A better method would be to create the MessageType as an array, then you could stack messages, but the above provides the basics.
Essentially, change the trigger script to accept multiple entries, you could use a while loop with 'shift' and PlistBuddy to populate. Then use PlistBuddy in the LaunchAgent script, you could read item 0 of the array and then delete item 0 - repeat until item 0 is non-existent.
Posted on 05-18-2016 10:33 AM
Has anyone tried running terminal-notifier this way in 10.11.4 yet? following the launchctl option i am getting this error
Script result: Could not find service "com.company.launchnotification" in domain for login: 100019
wondering if anyone has any knowledge of this or a work around.
Posted on 05-18-2016 10:54 AM
@b3nnb You may want to read through this thread. https://jamfnation.jamfsoftware.com/discussion.html?id=9902
In particular look at the posts near the bottom where @Josh.Smith mentions the right way to use launchctl as of 10.11 for running commands as the user. This method has been working very well for me on any systems at 10.10 and up.
Posted on 09-04-2016 09:29 PM
Worthwhile read...
LAUNCHCTL 2.0 SYNTAX
https://babodee.wordpress.com/2016/04/09/launchctl-2-0-syntax/