Shell Script Template
Tags: bash, linux, devops, tips
Published: 2021-02-27 12:56:25

# Record everything in a shell script

Usually when I work with source code in a software project, no matter it is Java, Python, or any other languages, there are some infrastructure set up tasks that need the use of shell scripting.

It is very useful to record EVERY shell commands that involve the source code. For example, when you initialize a NextJs project, you would write `yarn create next-app your-app`. It is not a waste of time to record this in a utility script so that you and your friend know EVERYTHING commands that involve the project.

```bash
#!/bin/bash

init_project() {
    yarn create next-app your-app
}
```

Suppose you have a command to be used in CI/CD configuration tools such as Gitlab CI, you write all the core command in this shell script and have Gitlab CI invoke your script.

```bash
# In your utility.sh
build_and_deploy_to_k8s() {
    yarn build
    build_docker_image
    publish_docker_image
    deploy_to_k8s
}
```

```yml
# In your .gitlab-ci.yml
deploy:
    stage: deploy
    script:
        - ./utility.sh build_and_deploy_to_k8s
```

With this practice, you verbosely declare almost everything in the source code. The future you and your friends will share equal knowledge of what happens in the whole life cycle of the project and can investigate and reproduce any issue.

To do this, your `utility.sh` will need some common features:
1. You can add a new group of commands in a bash function and invoke the function easily, like `./utility.sh your_new_function`.
2. You can add documentation to your commands so that they can be shown when the user executes the script with `./utility.sh help` 
3. The `./utility.sh help` command can list all the available commands and their documentation.
4. You can add private commands that do not show to the user and cannot be invoked externally.
5. The script can handle when the user enters an invalid or no command.
6. The script has an easy error handling mechanism.
7. The script is in compliance with [shellcheck](https://github.com/koalaman/shellcheck) standard.

# My template

I share my template that work for me in most case in my [Github](https://github.com/asinkxcoswt/shell-script-template), please check it out.

# Example Usage


```shell
$ ./example.sh

alert
	To print a normal message with a cute cow.

all_commands
	Show all available commands

error
	To print an error message with a cute cow, and then exit the script with non-zero exit code

ex_happy
	Test happy case

ex_oops
	What will happens when there is an error that your forgot to handle with && and ||

ex_public_command
	All function that starts with _ will now be listed and cannot be invoked externally.
 But you can still invoke the function inside the script itself.

ex_success_or_failure
	This example show you the error handling behavior.
 You can use || and && to handle in case your command fails.
 If a command in a pipe fails, all the pipe also fails

ex_unhappy
	Test the "error" command

greeting_n_times
	your documentation

help
	Show all available commands and their documentation

$ ./example.sh greeting_n_times

 ______________________
  < Missing 1st parameter for name of the person >
 ----------------------
        \   ^__^
         \  (xx)\_______
            (__)\       )\/
             U  ||----w |
                ||     ||

$ ./example.sh greeting_n_times John

 ______________________
  < Missing 2nd parameter for the number of time to say hello >
 ----------------------
        \   ^__^
         \  (xx)\_______
            (__)\       )\/
             U  ||----w |
                ||     ||


$ ./example.sh greeting_n_times John 3
Hello John
Hello John
Hello John
```