Mac OS X: Refreshing service menus works in Terminal but not in post-install-script - macos

I have an OSX application providing a service menu to other applications. This works fine so far, the menu is activated and available after a user installed the app and logged out and back in. (see similiar post)
I know the log-out-and-back-in is obsolete when triggering the service menu agent (pbs) to scan for changed services by opening a terminal and running
/System/Library/CoreServices/pbs
(this also works without having the new application launched even once)
So I´d like to provide an installer (.pkg) which runs "pbs" as post-install script. Suprisingly, running "bps" as post-install only works if the application was launched before e.g.:
#! /bin/sh
sleep 3
open /Applications/MyApp.app
sleep 3
/System/Library/CoreServices/pbs
exit 0
Unfortunately, (due to application specific reasons) I do not want to start my application directly from the installer. Does anyone know why the post-install-scrips behaves different than the Terminal?

Depending on the rights the Installer requires the post-install scripts maybe runs as root user. Try:
sleep 3
su -l "${USER}" -c "open /Applications/MyApp.app"
sleep 3
su -l "${USER}" -c "/System/Library/CoreServices/pbs"
exit 0

Eventually, as a workarround, I am going to start my application hidden and stopping it again before running pbs. Still looking forward for a better solution.

Related

Is there a way to get my laptop to beep from within a bash script running on a remote server via SSH?

I have a bash script that I have to regularly run on a remote server. Part of the script includes running a backup which takes a while, and after it has run, I have to hit "Y" to confirm that the backup worked before the script will continue.
I would like to know if there is a way to get my laptop to make a beep (or some sort of sound) when that happens. I know that echo -e '\a' makes a beep, but if I run it from within a script on the remote server, the beep happens on the remote server.
I have control of the script that is being run, so I could easily change it to do something special.
You could send the command through ssh back to your computer like:
ssh user#host "echo -e '\a'"
Just make sure you have ssh key authentication from your server to your computer so the command can run smoothly
In my case the offered solutions with echo didn't work. I'm using a macbook and connect to an ubuntu system. I keep the terminal open and I'd like to be informed when a long running bash script is ready.
What I did notice is that if I shutdown the remote system then it will beep the macbook and show an alarm icon on the relevant tab. So I have now implemented a bit of dirty workaround:
sudo shutdown 1440 && shutdown -c
This will initiate the system to shutdown and will immediately cancel the request. And I do get the alarm beep + icon. You will need to setup sudo to allow the user to permit shutdown. As it was my own remote server it was no problem but could limit the usability for others.

How to hide/quit terminal while program is still running in OS X?

I'm doing my project and I need to log keystrokes system wide in macOS. So, I turned over to GitHub and found Swift-Keylogger. The only problem is I can't quit the Terminal while the program is still running.
Is there any way to not to run this in terminal or closing the terminal window instead of creating a mac app like here.
Note: There are some mac app style executables in github but they are not providing the output I want and some need additional permissions.
Instead of running the executable like ./Keylogger use nohup ./Keylogger &.
You can quit the Terminal after executing the command.
To kill the Keylogger, run ps -e | grep "Keylogger" to get pid and kill -9 pid.
P.S. I thought of adding it as well as running at startup but I'm too lazy to update the repository.

Auto Restart SH script on crash?

Hi there guys i have a server running a game I've created and it has three SH scripts that are required to run in separate terminals so what i wanna know is 2 things.
1:is there a way i can get a single script that i double click on and launch all three scripts to where i can see the shell (for Debugging)
2: Is there any way to have said scripts auto restart when they exit or crash? (for full automated access when the server is unattended by a dev)
Server Specs:
6gb ram 60gb SSD 6 core CPU
Ubuntu 14.04
with vnc for desktop control
Here's a SH script for you.
running=1
finish()
{
running=0
}
trap finish SIGINT
while (( running )); do
// Execute the command here that starts your server.
echo "Restarting server on crash.."
sleep 5
done
You can run this script for each server in it's own screen. That way you can see the console output of each one. For example:
screen -S YOURUNIQUENAME -m THESCRIPTABOVE.sh
In order to detach from the screen, hit CTRL + A then CTRL + D. You can get back to the screen by using screen -x YOURUNIQUENAME
For a nice guide on using the screen command, see this article: http://www.rackaid.com/blog/linux-screen-tutorial-and-how-to/ . It even has a video to show how it's used.

stopping LaunchAgent when uninstalling package

I build an app which provides LaunchAgent (an small UI app with "tray" icon; let's say that defined in /Library/LaunchAgents/foo.plist.
When installing package launchctl loads this LaunchAgent description automatically and starts processes for all logged-in users. (i.e i don't have to load it using launchctl load like i have to do with LaunchDaemons).
When i uninstall package, all files - including LaunchAgent plist file in /Library/LaunchAgents are removed but processes are still running.
(i have several users logged in, so there are several instances of this agent)
Now, how should i tell root launchd to stop these processes (for unspecified number of users) when running as root ? (note, launchctl ran as root doesn't even see those agents).
(pid-files,killall more-or-less-unique-executable-name is last resort and i'm keeping these solution as last resort)
Try this:
LOGGEDUSERS=`who | grep console | awk '{ print $1 }'`
for CURRUSER in $LOGGEDUSERS
do
su -l $CURRUSER -c 'launchctl unload /Library/LaunchAgents/your.plist'
done
In my uninstaller script there is also killall -15 <app_name> after that code (just in case)

How can you start a LaunchAgent for the first time without rebooting, when your code runs as a LaunchDaemon?

I have a LaunchDaemon. When it runs, it checks if SIMBL is installed. If SIMBL is not installed, it uses NSTask to run /usr/sbin/installer on the SIMBL.pkg.
SIMBL's postflight script then tries to run a launchctl load command to start SIMBL's LaunchAgent immediately:
sudo -u "$USER" -- /bin/launchctl load -F -S Aqua -D user "${LAUNCHD_PLIST}"
This fails, because my LaunchDaemon's NSTask environment doesn't have $USER set.
If I have my daemon detect the current user with the System Configuration framework and pass it to NSTask with setEnvironment, launchctl bugs out on me:
Bug: launchctl.c:2325 (23930):13: (dbfd = open(g_job_overrides_db_path, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1
I realize a daemon, by definition, should not operate in a user session. By the same token, Apple seems to recommend LaunchAgents as helper objects for LaunchDaemons, to do that user session work. Is there any way to get such an agent up and running immediately?
I have all the .plists in the right places (they start running after a reboot, the next time launchctl does its regular loading) so my first thought was to just tell launchctl to reload. But all the code to do that is commented out in launchctl.c:
// { "reload", reload_cmd, "Reload configuration files and/or directories" },
...
* In later versions of launchd, I hope to load everything in the first pass,
* then do the Bonjour magic on the jobs that need it, and reload them, but for now,
* I haven't thought through the various complexities of reloading jobs, and therefore
* launchd doesn't have reload support right now.
Oh how launchd drives me crazy....
To cut to the chase, after much study and experimentation, this is how I do it on 10.5+:
# If possible, tell launchd to start the LaunchAgent. This will fail on 10.4.
# $F[0] is the pid
# $F[1] is the username
# $F[2] is the first word of the command
ps -ww -A -opid,user,command | \
perl -nae 'if($F[2] =~ /\bloginwindow\b/) { system(
qq(launchctl bsexec $F[0] su $F[1] -c "launchctl load -w <your_plist>"))
}'
I have found no way to achieve this directly on 10.4. I cheat on 10.4 and just run the thing the LaunchAgent would have run, even though it has a GUI and you're not supposed to be able to do that (you can anyway in 10.4-10.6; you can't in 10.7). On 10.4, the LaunchAgent works correct after the next reboot.
The above code looks for loginwindow processes and uses bsexec to run commands in those contexts. Keep in mind that with Fast User Switching, there can be multiple contexts.
Some useful links:
Daemons and Services Programming Guide. You have to read it, but it won't actually answer any of the hard questions. But it will at least give you hints at where everything is located.
TN2083. This is a maddening document that raises as many questions as it answers, but is gospel and mandatory reading for anyone entering the abyss of launchd.
Starting/stopping a launchd agent for all users with GUI sessions. This has several other useful links and explanation.
IMO, launchd is one of the worst "great ideas" Apple has ever deployed. The idea is very useful, but the API is horrible.

Resources