Writing a shell script to automate running multiple services/tasks in different terminals in macOS
What is a shell ?
→ A computer program through which you or your program can interact with the operating system .
This interaction can be using commands (CLI — command-line interface) or using graphical interface (GUI) .
GUI (Graphical User Interface) →
In Windows , you get Windows Shell , that is nothing else than the Desktop , Taskbar , Startmenu etc that you use on daily basis to interact with the system . Similary the graphical shell for macOS which you must be using from time to time is Finder.
CLI (Command-line Interface) →
In Windows systems , you have CommandPrompt or cmd.exe and in Unix-like systems you have unix shells like sh , zsh , Bash etc .
So , instead of allowing you to interact via graphics , this interface takes text commands to interact with Operating System .
A Unix shell is a command-line interface/ interpreter or shell that provides a command line user interface for Unix-like operating systems.
Some commonly used unix shells are -
1. The Bourne Shell (sh)
2. The GNU Bourne-Again Shell (bash)
3. The Z Shell (zsh)
What is a shell script ?
A shell script is nothing but just a sequence of multiple commands or a computer program written in a single script file . The shell is both an interactive command language and a scripting language, and is used by the operating system to control the execution of the system using shell scripts
While typing commands into Apple’s Terminal or Windows cmd is typically done one by one, with a script, you can execute a long list of commands with just one interaction.
How to write the shell script ?
1 . The first line →
It lets the command line processor know that incoming text file is a not just a normal text file , it’s a script .
If using bash , then add following in the first line of the script file:
#!/bin/bash
OR If using zsh →
#!/usr/bin/env zsh
OR If using sh →
#!/bin/sh
2. The commands →
Now , what we want to do is give commands in the script where we ask the terminal(shell) to open a new terminal window and execute some commands inside the new terminal . Let’s start with printing a normal echo message .
The script (macOs)→
#!/usr/bin/env zshecho “Running my script . . . “osascript -e “tell application \”Terminal\” to do script \”echo HelloWorld\””
The above script contains more than just shell script , it also has AppleScript .
— — — — — — — — — — — — — — — — — — — — — — — — — —
AppleScript ? → AppleScript is a scripting language created by Apple. It allows users to directly control scriptable Macintosh applications, as well as parts of macOS itself.
— — — — — — — — — — — — — — — — — — — — — — — — — —
Let’s break the command -
- echo → standard output command
- osascript → used to execute AppleScript
- -e command → used to enter one line of a script .
- following “” → contains the AppleScript (‘tell application \”Terminal\” to do script \”echo HelloWorld\”’) — which is quite self-explainatory .
→ You may save 💾 the text file as “yourScript.sh”
→ To run the script , run the following in a terminal window :-
sh {path_of_script}/yourScript.sh
Using Variables →
Now , you can simply replace this echo command with your commands to run or start your services .
Example →
#!/usr/bin/env zshecho “Running my script to start a service. . . “startServiceCommand=”java -jar /{path-to-the-jar}/myService.jar”osascript -e “tell application \”Terminal\” to do script \”${startServiceCommand}\””
Here we have used a variable called — startServiceCommand to store the command to be run to start our service , and this can be passed in the AppleScript as shown above.
Note — Make sure you don’t give any spaces around the “=” used while assigning the command to variable , otherwise you will end up having “command not found
” error while executing script .
Running Multiple Services →
#!/usr/bin/env zshecho “Running my script to start multiple services. . . “startServiceA=”java -jar /{path-to-the-jar}/myServiceA.jar”startServiceB=”java -jar /{path-to-the-jar}/myServiceB.jar”osascript -e “tell application \”Terminal\” to do script \”${startServiceA}\””osascript -e “tell application \”Terminal\” to do script \”${startServiceB}\””
Now , what if you have a requirement such as a delay is required in between two commands ? Let’s say serviceB is dependent on serviceA i.e it requires serviceA to be up and running before serviceB is started .
Once you run the above script , you will notice that both the commands are executed almost instantly without any delay , although serviceA will start before according to the script execution order , but script will immediately execute next command to start serviceB , resulting in serviceB failure .
Adding Delay in script→
You can simply put a sleep command in between the commands to add a delay in your shell script .
#!/usr/bin/env zshecho “Running my script to start multiple services. . . “startServiceA=”java -jar /{path-to-the-jar}/myServiceA.jar”startServiceB=”java -jar /{path-to-the-jar}/myServiceB.jar”osascript -e “tell application \”Terminal\” to do script \”${startServiceA}\””sleep 5osascript -e “tell application \”Terminal\” to do script \”${startServiceB}\””
- Now , this script will wait for 5 seconds before running last command to start service B . To give sleep in either minutes or hours , you can use sleep value as respective alphabetical notation like -> 2m for 2 minutes and 3h for 3 hours .
This is it , your basic shell script is ready to use , we used shell script that contained an AppleScript to run our services . You can now automate any manual process that you may have using relevant commands . Please note this example used commands to open new terminal windows for each AppleScript execution which I wanted to share , your requirement might not be the same.