Build A Cross Platform Shell Script CLI Runner
Developers in teams might prefer using different operation systems such as Windows and MacOS. Some members write scripts for projects in PowerShell and others write them in Bash. It causes the other members who use different operation systems can run these scripts. After, some tries end errors. We came up an idea to create our own script runner that can execute bash script regardless the OS easily.
The Idea
We like the idea of npm and make commands, we can define the project-related scripts in package.json and makefile. It makes scripts re-useable and makes other people who doesn’t work on the project before know how to get started the projects. However, there are some disadvantages for npm and make commands. For npm, each script cannot be too long. For make, it cannot be run on windows. After some experiments, we came up some requirements:
- like makefile, the scripts are defined in a file.
- the scripts can be executed cross platform and be executed easily.
- easy to setup
The Solution
We decided using golang to build the CLI because
- the compiled binary can be executed cross platform
- for golang users, we can use
go get path/to/repo
to install the CLI - for non-golang users, we can create an install script which is like the install script of chocolatey or homebrew to install the CLI. And non-golang users don’t need to install golang runtime which is unlike CLI built by nodejs
- the standalone binary is smaller than the binary built by other programming language such .net core
Then create a .scripts.yml
file in the root of projects. Its structure are
For example, this is the .scripts.yml
for the example repo.
Then, we can run below commands to execute defined scripts.
The magic to let windows users run bash-like script is pretty simple. We uses git-bash.exe
to execute the script. All of our windows developers have install git for windows. It is not an extract step to install another package.
This is the snippet to find the path of bash binary
The shellPath will be C:\Program Files\Git\bin\bash.exe
on windows and /bin/bash
on unix-like os. Then we use exec.Command
to open the bash and stdin the script.
For environmental variables, exec.Command
will pass the envs to shell from the current session. We can use os.Setenv
to add some other envs to the shell. Then, the script can read these environmental variables.
Also, there are some major reasons we use git-bash.exe instead of wsl.exe
- not all developers enable WSL, but all developers install git in our teams.
- WSL is a VM. It might cause problem if the script wants to access or write files in HOME like
~/file
, because HOME of WSL is different of HOME of windows. - the script run by wsl.exe won’t get environmental variables from the current session.
Conclusion
This is the method that our teams can run bash scripts that can be executed in spite of the operation systems they use. Maybe building a CLI for that is overkill but we developers who love to craft some things 😁. And we feel that use the CLI is easier than create multiple bash scripts and execute them. This is the example repo. The repo is just for demonstrating the idea which we extracted some code from our private repo. The really CLI has many our custom features, that make our works easier and projects neater.