Wait until a certain application has exited, then launch another one - macos

On OS X I want to execute an osascript command that waits until a certain application specified by its full .app path has exited, then start another application, e.g. using /usr/bin/open -n /Applications/MyApp.app.
How to achieve the waiting until the application has exited?

A common approach is to perform a waiting loop, for example with pgrep:
while pgrep -f /Applications/TextEdit.app 2>/dev/null ; do sleep 1.0 ; done
Unfortunately, this will sleep too much and delay the start of the other application.
Alternatively, if you know that the application is running, you can use /usr/bin/open:
open -g -W /Applications/TextEdit.app
Unfortunately, this will open the application if it was not running. You could check it is running before calling /usr/bin/open, but this wouldn't be atomic: it could be closing and the open command could restart it.
Both can be encapsulated in osascript (although it probably doesn't make much sense).
osascript -e 'do shell script "while pgrep -f /Applications/TextEdit.app 2>/dev/null ; do sleep 1.0 ; done"'
osascript -e 'do shell script "open -g -W /Applications/TextEdit.app"'
As a side note: open -W actually performs a kqueue wait (non-polling wait) on the process. There might be other commands invoking kqueue and performing the same task without risking restarting the application. It is quite easy to implement in C.

Related

sending ctrl-c in bash to perf command

The perf-stat command in linux runs until crtl-c is pressed. I am trying to use this command in script to profile a loop. The recommended solution to simulate sending crtl-c is to issue a kill command with -2 or -SIGINT flag.
However this does not work for me. I am on RHEL.
The script more or less looks as follows:
for i in {1..12}
do
pid=$1
perf stat -e dTLB-loads -p $pid > perf.out&
perf_pid=$!
sleep 10
kill -SIGINT $perf_pid
done
Even after the kill the perf process is still active. All the ctrl-c's are executed at the end when the script gets over.
Reading the man page for perf, I came across the --control option which seems is the proper approach to profile a portion of running command.
However, this option is not available on RHEL .
I was able find workaround by using the -INT option for kill mentioned here. For some reason -2 or -SIGINT doesn't work on RHEL.

How can I prevent idle sleep in a long-running bash script on Mac OS?

I have a bash script that executes several long-running commands on Mac OS. How can I prevent the computer from going to sleep while the script is running?
I found that I can achieve the desired behavior by adding this line to the start of the script:
caffeinate -i -w $$ &
How it works:
caffeinate is a built-in Mac OS utility for creating power management assertions to prevent sleep.
The -i flag tells caffeinate to prevent idle sleep.
The -w flag tells caffeinate to wait until the specified process finishes.
$$ is a shell variable containing the current PID. Together with the -w flag this tells caffeinate to prevent sleep for the duration of the shell script.
The final & runs the command in the background so the script can continue running.

How to execute an application in bash that is not a child and keeps running?

I am writing a bash script and am checking whether the application is running. If it is not running it should be started in a separate process (not a child process). If it is running, the window should be maximized. I kind of made it but the new process terminates shortly after being started, probably because the script process ends.
#!/bin/bash
if (ps aux | grep App1 | grep -v grep > /dev/null)
then
echo App1 is running
wmctrl -x -r WMClassOfApp1 -b "add,maximized_vert,maximized_horz"
else
echo App1 is not running
sh -c /usr/bin/app1 & disown # This app should be started in a separate process and not terminate
fi
I probably have to add that I am calling this script from a udev rule. When I execute it in a terminal, it works fine. When I call it from the udev rule, the app1 terminates.
A bash script is not the right solution for this: best is to add this to crontab of your system.

Running processes simultaneously, Bash

I would like to run n processes (in my case simulations) simultaneously, using bash.
Right now this is what I'm running:
for file in $ini/SAN*.ini;
do
echo "Running $file...";
temp=$(basename $file .ini)
mosrun -G opp_run -r 0 -u Cmdenv -n ..:../../src -l ../../src/inet SAN.ini > $outputs/$temp.out;
done
Problem is, the loop only progresses to the next iteration after the simulation is done. Any suggestions? Thanks!
You should be able to run your command in the background by adding a & after it.
Should make them run in parallell, although in the background.
(Small side note: the processes will continue to run even if you abort the script, so you might want to add a trap to kill the processes if you hit for eg. ctrl-c when script is running. Look at bash manual.)

How do I write a watchdog daemon in bash?

I want a way to write a daemon in a shell script, which runs another application in a loop, restarting it if it dies.
When run using ./myscript.sh from an SSH session, it shall launch a new instance of the daemon, except if the daemon is already running.
When the SSH session ends, the daemon shall persist.
There shall be a parameter (./myscript -stop) that kills any existing daemon.
(Notes on edit - The original question specified that nohup and similar tools may not be used. This artificial requirement was an "XY question", and the accepted answer in fact uses all the tools the OP claimed were not possible to use.)
Based on clarifications in comments, what you actually want is a daemon process that keeps a child running, relaunching it whenever it exits. You want a way to type "./myscript.sh" in an ssh session and have the daemon started.
#!/usr/bin/env bash
PIDFILE=~/.mydaemon.pid
if [ x"$1" = x-daemon ]; then
if test -f "$PIDFILE"; then exit; fi
echo $$ > "$PIDFILE"
trap "rm '$PIDFILE'" EXIT SIGTERM
while true; do
#launch your app here
/usr/bin/server-or-whatever &
wait # needed for trap to work
done
elif [ x"$1" = x-stop ]; then
kill `cat "$PIDFILE"`
else
nohup "$0" -daemon
fi
Run the script: it will launch the daemon process for you with nohup. The daemon process is a loop that watches for the child to exit, and relaunches it when it does.
To control the daemon, there's a -stop argument the script can take that will kill the daemon. Look at examples in your system's init scripts for more complete examples with better error checking.
The pid of the most recently "backgrounded" process is stored in $!
$ cat &
[1] 7057
$ echo $!
7057
I am unaware of a fork command in bash. Are you sure bash is the right tool for this job?

Resources