Writing shell scripts
Writing shell scripts
When you are using your terminal a lot during the day make sure to improve your workflow and reduce the number of keystrokes you have to type to perform your daily tasks.
This post will only outline the options and not go to deep into details. There are great posts out there that describe all the details way better than I could.
The focus of this post is a basic overview what you can do and why you want to invest time in your tooling on a shell level.
What can shell scripts do for you and your team?
It is nice to optimize your own workflow - enabling a whole team to be faster and deliver software with better quality is just amazing.
Decrease onboarding time
When you enter a new team with there development processes and tools might be intimidating at times. Having great tools and scripts makes this easy and even fun for new engineers joining a team. They can focus on finishing the first tasks early and actually contribute from day one without having to learn nifty little details.
Streamline tooling
In case updates to the flow (having extra steps, parameters) can be handled centrally.
Start small
To get used to writing shell scripts that you actually use and make your daily work easier and faster start small.
What does that mean?
Let's assume you have some command that you use for deploying your application. In my case that is a serverless backend on AWS. We use the serverless framework in a multi-repo managed with lerna
npx lerna exec --scope @some/package \
--stream sls -- deploy -v \
--param1 value1 \
--param2 value2
You can always look it up in your history or wrap it in a little script called deploy
. Do not forget to give the script the permission to be executed (chmod +x deploy
)
#!/bin/bash
npx lerna exec --scope @some/package
--stream sls -- deploy -v \
--param1 value1 \
--param2 value2
Now you only have to remember the command deploy
. Later you might notice that you can only deploy a specific package because it is hard coded in the script.
Let's change that!
Simple parameters
You can access simple parameters by using $[number]
.
#!/bin/bash
PACKAGE_NAME=$1
npx lerna exec --scope "@some/${PACKAGE_NAME}" \
--stream sls -- deploy -v \
--param1 value1 \
--param2 value2
Now you can deploy whatever package you want by running
deploy package
deploy otherpackage
An optional parameter to deploy a single function
A lot of times I just change one function and just want to test that in Lambda. So let's extend our little script to include the option to deploy a single function.
#!/bin/bash
PACKAGE_NAME=$1
FUNCTION_NAME=$2
# Do we have a function name?
if [ "${FUNCTION_NAME}" != "" ]; then
# Seems like it, so let's create the correct parameter
FUNCTION_PARAM="--function ${FUNCTION_NAME}"
fi
npx lerna exec --scope "@some/${PACKAGE_NAME}" \
--stream sls -- deploy -v \
--param1 value1 \
--param2 value2 \
# Append the parameter, if it is empty - nothing gets added
"${FUNCTION_PARAM}"
Next steps
The next steps are a bit more advanced and might be frustrating at times to make them work. Keep at it, the result is usually amazing for you and your team.
Autocompletion
How to enable autocompletion depends on the shell you are using. Refer to your manual. I use the zsh on a Mac with oh-my-zsh.
An example to autocomplete our deployment script with a single function to deploy
#compdef
_deploy_package() {
local -a functions
# Extract functions from serverless.yml
functions=$(grep '^[^[:blank:]]\(.*\):$' ./path/to/serverless.yml | tr -d ':')
_alternative "argument:group:($functions)"
}
...
_deploy() {
local line
# Autocompletion for our commands
_commands() {
local -a commands
commands=(
'package:Deploy @some/package'
'otherpackage:Deploy @some/otherpackage'
)
_describe 'command' commands
}
_arguments -C \
"1: :_commands" \
"*::arg:->args"
# Autocompletion for the commands - in this case to list all functions
# from our serverles.yml
case $line[1] in
package) _deploy_package ;;
otherpackage) _deploy_otherpackage ;;
esac
}