Back to bash: Inception, running bash inside bash
Tags: bash, shell, linux
Published: 2024-02-02 23:07:45

This post will be a shorter one that goes into different ways of running bash scripts inside bash (interactive shell or another bash script). While in general it is a fairly simple process, there are some useful things to keep in mind. At first i wasn't sure if it warranted it's own post, but I've been meaning to make my blogs a bit shorter, and I'm happy how it turned out in the end.

There's essentially two main ways of running another bash script inside bash (spoiler, there is a third way, but i suspect you won't use it as often).

## Running a script by specifying the path

First things first, any script you try to run directly must have executable permissions. This is not the default when creating files, so you must remember to add them. As an example, granting only the user that owns the file access to execute it can be done using `chmod u+x a.bash`.

To run another bash script, simply specify the path, as in `./a.bash`, to run it in the current working directory. Note that this is no different from how you would run any other program. Also note that the path to the script/executable must be given, hence the `./` prefix. Bash will do a few things under the hood:

1. Prepare a new execution environment for the command. This contains a couple of things [^1], the most important of which are the current working directory and the environment variables. These are inherited from the parent execution environment. 
2. Run the script into a new bash process with the newly prepared execution environment. Any changes the script makes to its environment do not affect the parent. As an example, consider the following script that sets an environment variable (export) 

```console
export ABC="42"
cd ../
```

When executed, we can observe that the `ABC` variable is not available in the environment of the parent, nor is the working directory altered.

```console
~/some_dir/other_dir$ ./a.bash 
~/some_dir/other_dir$ echo $ABC
```

## Sourcing the script

The source builtin, as in `source a.bash` or `. a.bash` (the first is just an alias for the latter), can be used to execute all commands from a given script in the current execution environment, allowing you to effectively run scripts that alter the environment and the working directory. The example from above is shown again, but this time it affects the shell.

```console
~/some_dir/other_dir$ source ./a.bash 
~/some_dir$ echo $ABC
42

```

## Running scripts from PATH

Remember how i said the executable must be specified as a path? That is because, when bash does not see a path (no slashes), it will try to look for an executable in any of the PATH directories. This can be desirable if you want to make a script readily available from any location. For example, if you add the `a.bash` file from before to `/usr/local/bin`, you can run it, like any other program, using its name, `a.bash` (assuming `/usr/local/bin` is in the PATH variable).


## A final remark

At the very top of a file you want to execute, you can specify what is called a shebang [^2]. This will be picked up in most Unix systems, and indicates what interpreter should be used to run the script. 

```
#!/usr/bin/bash
...
```
In fact, it is good practice to put this in shared executable scripts as it ensures that bash will be used even if someone tries to run it in a different shell. 

You can also use this to run scripts in other interpreters, such as python, so that you can use `some_script.py` rather than `python some_script.py`. If you then drop the .py extension, you can obfuscate the fact that it's running python entirely. 

[^1]: Among others, the execution environment also includes aliases and signal traps. For a full overview, check the bash manual or `man bash` help pages.
[^2]: Apparently this is a [contraption of the 2 characters](https://en.wikipedia.org/wiki/Shebang_(Unix)) used, I never would have guessed that though...