Friday, 6 February 2026

sourcing a script inside another script

Lets' create a shell script with a simple function to log messages , this shell script will be sourced from other shell script .


[root@oel01db Shell-Scripting]# cat utils.sh

log_message() {

    local level=$1

    local message=$2

    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")


    case "$level" in

        "INFO")  echo -e "[$timestamp] \e[32mINFO\e[0m: $message" ;;

        "ERROR") echo -e "[$timestamp] \e[31mERROR\e[0m: $message" ;;

        *)       echo -e "[$timestamp] DEBUG: $message" ;;

    esac

}

[root@oel01db Shell-Scripting]#


Create a simple script to check the existance of a user and its primary group and let's source above script .


[root@oel01db Shell-Scripting]# cat deploy.sh

#!/bin/bash


# 1. Source the utility functions

# Make sure utils.sh is in the same directory!

source ./utils.sh


# 2. Capture the first argument

USERNAME=$1


# 3. Validation: Check if the user provided an argument

if [ -z "$USERNAME" ]; then

    log_message "ERROR" "No username provided. Usage: $0 <username>"

    exit 1

fi


log_message "INFO" "Checking existence of user: $USERNAME"


# 4. Logic: Search for the username in /etc/passwd

if id "$USERNAME" &>/dev/null; then

    log_message "INFO" "User '$USERNAME' exists on this system."


    # Optional: Show their primary group

    USER_GROUP=$(id -gn "$USERNAME")

    log_message "INFO" "Primary group for $USERNAME: $USER_GROUP"

else

    log_message "ERROR" "User '$USERNAME' does not exist."

    exit 1

fi

[root@oel01db Shell-Scripting]#

How  "if id "$USERNAME" &>/dev/null; then" works ? 

In Bash, if doesn't just check for "true" or "false." It specifically checks the Exit Status of the command that follows it.

  • If the exit status is 0 (Success), it runs the code after then.

  • If the exit status is anything else (Failure), it jumps to the else block.


















How to use -p with source

[root@oel01db Shell-Scripting]# ls -lrt
total 8
-rw-r--r-- 1 root root 340 Dec 23 10:01 utils.sh
-rw-r--r-- 1 root root 765 Dec 23 10:02 deploy.sh
drwxr-xr-x 2 root root   6 Dec 23 10:17 lib
[root@oel01db Shell-Scripting]# cp utils.sh lib/
[root@oel01db Shell-Scripting]#


[root@oel01db Shell-Scripting]# cat deploy_lib.sh
#!/bin/bash

# 1. Source the utility functions using libdirs

libdirs=./lib

. -p "$libdirs" utils.sh

# 2. Capture the first argument
USERNAME=$1

# 3. Validation: Check if the user provided an argument
if [ -z "$USERNAME" ]; then
    log_message "ERROR" "No username provided. Usage: $0 <username>"
    exit 1
fi

log_message "INFO" "Checking existence of user: $USERNAME"

# 4. Logic: Search for the username in /etc/passwd
if id "$USERNAME" &>/dev/null; then
    log_message "INFO" "User '$USERNAME' exists on this system."

    # Optional: Show their primary group
    USER_GROUP=$(id -gn "$USERNAME")
    log_message "INFO" "Primary group for $USERNAME: $USER_GROUP"
else
    log_message "ERROR" "User '$USERNAME' does not exist."
    exit 1
fi

[root@oel01db Shell-Scripting]#


Sometime you may want to put some code that you want to execute only when source fail for any reason in that case you can use 



[root@oel01db Shell-Scripting]# cat utils.sh

log_message() {

    local level=$1

    local message=$2

    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")


    case "$level" in

        "INFO")  echo -e "[$timestamp] \e[32mINFO\e[0m: $message" ;;

        "ERROR") echo -e "[$timestamp] \e[31mERROR\e[0m: $message" ;;

        *)       echo -e "[$timestamp] DEBUG: $message" ;;

    esac

}


if ! ( return 2> /dev/null); then


      log_message "hi" "hello there"


fi


[root@oel01db Shell-Scripting]# cat deploy.sh

#!/bin/bash


# 1. Source the utility functions

# Make sure utils.sh is in the same directory!

source ./utils.sh


# 2. Capture the first argument

USERNAME=$1


# 3. Validation: Check if the user provided an argument

if [ -z "$USERNAME" ]; then

    log_message "ERROR" "No username provided. Usage: $0 <username>"

    exit 1

fi


log_message "INFO" "Checking existence of user: $USERNAME"


# 4. Logic: Search for the username in /etc/passwd

if id "$USERNAME" &>/dev/null; then

    log_message "INFO" "User '$USERNAME' exists on this system."


    # Optional: Show their primary group

    USER_GROUP=$(id -gn "$USERNAME")

    log_message "INFO" "Primary group for $USERNAME: $USER_GROUP"

else

    log_message "ERROR" "User '$USERNAME' does not exist."

    exit 1

fi

[root@oel01db Shell-Scripting]#

[root@oel01db Shell-Scripting]# sh utils.sh

[2025-12-23 13:57:16] DEBUG: hello there

[root@oel01db Shell-Scripting]#

[root@oel01db Shell-Scripting]# sh deploy.sh mahesh

[2025-12-23 13:57:25] INFO: Checking existence of user: mahesh

[2025-12-23 13:57:25] INFO: User 'mahesh' exists on this system.

[2025-12-23 13:57:25] INFO: Primary group for mahesh: mahesh

[root@oel01db Shell-Scripting]#




Why "hello there" is not executed when we sourced the first script inside deploy.sh?

The command return is only valid inside a function or a sourced script.

  1. When you run sh utils.sh directly: utils.sh is executed as a standalone script and return is NOT allowed in a normal script. The ! (NOT) operator turns that failure into a "true" condition, so the code inside the if block executes. This is why you see "hello there".

  2. When you run source ./utils.sh (inside deploy.sh): The script is being loaded into the current shell environment. In this context, return is a valid command. Because return succeeds, the ! operator makes the condition "false," and the code inside the if block is skipped.


In the context of shell scripting, "returning" doesn't mean the script is sending back a specific piece of data (like a string or a number). Instead, it refers to the exit status of the command and how the shell handles the flow of execution.

[root@oel01db Shell-Scripting]# (return)
-bash: return: can only `return' from a function or sourced script
[root@oel01db Shell-Scripting]#


The "Failed" Return

When you run sh utils.sh, the shell executes the line ( return 2> /dev/null ).

  1. The shell says: "You're trying to return, but you aren't inside a function or a sourced script!"

  2. It generates an error exit status (usually 2 in most shells, but any non-zero number counts as a failure).

  3. The ! (logical NOT) takes that failure and turns it into True.

  4. The if block executes.




No comments:

Post a Comment

Deploy PostgreSQL Database Code to Dev and Test Environments Sequentially Using GitHub Actions

Deploy PostgreSQL Database Code to Dev and Test Environments Sequentially Using GitHub Actions Modern database deployments should be repeata...