How to call one shell script from another shell script?
Categories:
How to Call One Shell Script from Another Shell Script
Learn the different methods to execute a shell script from within another, understanding their implications for variable scope and execution environment.
Executing one shell script from another is a common practice in shell scripting, allowing for modularity, reusability, and better organization of your code. There are several ways to achieve this, each with distinct behaviors regarding how variables, functions, and the execution environment are handled. This article will explore the most common methods: sourcing, executing as a child process, and using the exec
command, providing practical examples and best practices.
Method 1: Sourcing ('. ' or 'source')
Sourcing a script means that the commands within the called script are executed in the current shell environment. This is particularly useful when you want to share variables, functions, or aliases between scripts. Any variables set or modified in the sourced script will affect the calling script's environment. This method is often used for configuration files or utility functions.
#!/bin/bash
# caller.sh
echo "Caller: Initial value of MY_VAR is $MY_VAR"
# Source the script
source ./callee.sh
echo "Caller: Value of MY_VAR after sourcing is $MY_VAR"
# Call a function defined in callee.sh
hello_from_callee
echo "Caller: After callee, MY_VAR is $MY_VAR and NEW_VAR is $NEW_VAR"
The calling script (caller.sh
) sourcing another script.
#!/bin/bash
# callee.sh
MY_VAR="Hello from Callee"
NEW_VAR="I am a new variable"
function hello_from_callee() {
echo "Callee: Hello from a function in callee.sh!"
}
echo "Callee: MY_VAR set to $MY_VAR"
The sourced script (callee.sh
) defining variables and a function.
source script.sh
or . script.sh
. The single dot .
is a POSIX standard and is generally preferred for portability.Method 2: Executing as a Child Process ('./script.sh' or 'bash script.sh')
When you execute a script using ./script.sh
(assuming it's executable) or bash script.sh
, it runs in a new subshell. This means it gets its own separate environment, which is a copy of the parent's environment at the time of execution. Any variables or functions defined or modified within the child script will not affect the parent script's environment. This method provides isolation and is the most common way to run independent scripts.
#!/bin/bash
# parent.sh
PARENT_VAR="I am from parent"
export EXPORTED_VAR="I am exported from parent"
echo "Parent: Initial PARENT_VAR = $PARENT_VAR"
echo "Parent: Initial EXPORTED_VAR = $EXPORTED_VAR"
# Execute the child script
./child.sh
echo "Parent: PARENT_VAR after child execution = $PARENT_VAR (should be unchanged)"
echo "Parent: EXPORTED_VAR after child execution = $EXPORTED_VAR (should be unchanged)"
echo "Parent: CHILD_VAR after child execution = $CHILD_VAR (should be empty)"
The parent script (parent.sh
) executing a child script.
#!/bin/bash
# child.sh
echo "Child: PARENT_VAR received = $PARENT_VAR (should be empty)"
echo "Child: EXPORTED_VAR received = $EXPORTED_VAR (should be 'I am exported from parent')"
PARENT_VAR="Modified by child"
CHILD_VAR="I am from child"
echo "Child: PARENT_VAR modified to = $PARENT_VAR"
echo "Child: CHILD_VAR set to = $CHILD_VAR"
The child script (child.sh
) modifying variables locally.
Method 3: Using 'exec'
The exec
command replaces the current shell process with the specified command or script. When you use exec
to call another script, the calling script terminates and the called script takes over its process ID. The calling script does not resume after the exec
command. This is useful when you want to pass control completely to another script without returning.
#!/bin/bash
# first_script.sh
echo "First Script: Starting... PID is $$"
VAR_FROM_FIRST="Hello from first script"
export VAR_FROM_FIRST
echo "First Script: About to exec second_script.sh"
exec ./second_script.sh
echo "First Script: This line will NEVER be reached."
The first script (first_script.sh
) using exec
to hand over control.
#!/bin/bash
# second_script.sh
echo "Second Script: Starting... PID is $$"
echo "Second Script: Received VAR_FROM_FIRST = $VAR_FROM_FIRST"
FINAL_VAR="I am from second script"
echo "Second Script: Done."
The second script (second_script.sh
) taking over the process.
exec
, indicating that the first script's process has been replaced by the second script.Comparison of script calling methods: Sourcing, Child Process, and Exec.
Summary and Best Practices
Choosing the right method depends on your specific needs:
- Sourcing (
.
orsource
): Use when you need to share variables, functions, or configurations directly with the calling script's environment. Ideal for library scripts or environment setup. - Child Process (
./script.sh
orbash script.sh
): Use for executing independent tasks or modules. This provides excellent isolation, preventing unintended side effects on the calling script. It's the most common and safest method for general script execution. exec
: Use when you want to completely hand off control from the current script to another, and the current script should not resume execution. This is less common but useful for specific scenarios like daemonizing processes or launching a new application from a wrapper script.
Always consider the scope of variables and the desired execution flow when deciding how to call one shell script from another. Understanding these distinctions is key to writing robust and maintainable shell scripts.