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

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.

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.

Execute command on second terminal in bash script

I am writing a bash script to execute 2 commands at a time on 2 different terminal & original terminal wait for both 2 terminal to finish & then continue with remaining script.
I am able to open a different terminal with required command, however the original terminal seems not waiting for the 2nd one to complete & auto close before proceeding with remaining of the script.
#!/bin/bash
read -p "Hello"
read -p "Press enter to start sql installation"
for i in 1
do
xterm -hold -e mysql_secure_installation &
done
echo "completed installation"
Use the Bash wait command to cause the calling script to wait for a background process to complete. Your for loop implies that you may be launching multiple background processes in parallel even though in your question there's only one. Without any options wait will wait for all of them.
I wonder why you're launching the processes in xterm instead of directly.

Open Multiple XTerm Windows Simultaniously

I am working on a Raspberry Pi powered Magic Mirror project and to start the program I execute a shell script that runs in the background continuously. To make the AI part of my project work I need to open a second shell script in the background that also runs continuously. My problem occurs when I try to execute my Xterm commands it waits for the first script to complete before it starts the second script. Since both scripts have no designated end point I am stuck. Is there a way to make both Xterm commands execute at the same time?
Here is my current code to start the Xterm sessions:
cd ~/MMStartAll
xterm -e "cd ~/MMStartAll; ./AssistantStart.sh"
xterm -e "cd ~/MMStartAll; ./MMStart.sh"
$SHELL
Your script should end with a &. This means that both the xterms will run in a sepperate process id (pid).
cd ~/MMStartAll
xterm -e "cd ~/MMStartAll; ./AssistantStart.sh" &
xterm -e "cd ~/MMStartAll; ./MMStart.sh" &
$SHELL

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

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.

BASH script suspend/continue a process within script

In my bash script I am writing, I am trying to start a process (sleep) in the background and then suspend it. Finally, the process with be finished. For some reason through, when I send the kill command with the stop signal, it just keeps running as if it received nothing. I can do this from the command line, but the bash script is not working as intended.
sleep 15&
pid=$!
kill -s STOP $pid
jobs
kill -s CONT $pid
You can make it work by enabling 'monitor mode' in your script: set -m
Please see why-cant-i-use-job-control-in-a-bash-script for further information

Resources