In Visual Code, on Windows 10, I'm trying to create a function for my .sh project (which I run with Git Bash), which will report errors to the console in case user, let's say, provides fewer or more parameters for a function.
For this reason, I created the file error_report.sh with the function ErrorReport.
#!/usr/bin/env bash
function ErrorReport()
{
local caller_func="${FUNCNAME[2]}"
local caller_file="$(basename "${BASH_SOURCE[2]}")"
local caller_line="${BASH_LINENO[1]}"
local caller_code="$(sed -n "${caller_line}p" "${BASH_SOURCE[2]}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
printf "\nCaller: ${caller_func}()"
printf "\nFile : ${caller_file}"
printf "\nLine : ${caller_line}"
printf "\nCode : ${caller_code}"
}
As main file of my project, I have temporarily created the tester_copy.sh where I have the following:
#!/usr/bin/env bash
declare -g script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${script_dir}/lib/ui/window_manager.sh"
source "${script_dir}/error_report.sh"
function TestFunction()
{
if [[ "$#" -ne 3 ]]; then
ErrorReport
return 1
fi
local arg1="$1"
local arg2="$2"
local arg3="$3"
echo "arguments: $arg1, $arg2, $arg3"
}
function Main()
{
ConsoleWindowSetup "${MMS_WINDOW_TITLE}" 40 120
clear
TestFunction "11111" "22222"
read -re -p ""
}
Main "$@"
The problem is that in my console, displays Caller and File correctly, but Line and Code incorrectly.
Instead of displaying Line: 28 and Code: TestFunction "11111" "22222", it displays:
Caller: Main()
File : tester_copy.sh
Line : 6
Code : source "${script_dir}/error_report.sh"
But if I change my main script to:
#!/usr/bin/env bash
declare -g script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${script_dir}/lib/ui/window_manager.sh"
source "${script_dir}/error_report.sh"
function TestFunction()
{
if [[ "$#" -ne 3 ]]; then
ErrorReport
return 1
fi
local arg1="$1"
local arg2="$2"
local arg3="$3"
echo "Λήφθηκαν τα arguments: $arg1, $arg2, $arg3"
}
ConsoleWindowSetup "${MMS_WINDOW_TITLE}" 40 120
clear
TestFunction "11111" "22222"
read -re -p ""
If I take the main code outside the function Main(), then it displays correctly in the console...
Caller: main()
File : tester_copy.sh
Line : 28
Code : TestFunction "11111" "22222"
Which I don't want though because ErrorReport is intended for errors inside functions.
Why is this happening and how can I make it work when the error is inside a function?
Debugging (17/05/2025)
If I copy the whole
.shproject into my Ubuntu Server it works even if the error is inside a function.It also works using WSL.
I am almost sure that the problem happens only if I run the
.shfile from Windows, by just double clicking on it. In any other case, works fine.
Debugging (18/05/2025)
The default application on this Windows computer to open .sh files is "C:\Program Files\Git\git-bash.exe". When I open my .sh file by double-clicking, the problem I mentioned occurs. However, if I try running it by dragging the file to "C:\Program Files\Git\bin\bash.exe", "C:\Program Files\Git\bin\sh.exe" or "C:\Program Files\Git\git-bash.exe", it works fine in all three!
I tried creating a shortcut with the target "C:\Program Files\Git\git-bash.exe" --cd="C:\Users\***\Desktop\PROGRAMMING\SH\sigma_sh_lib" -c "./tester_copy.sh" and it also works fine!
Then I created a function to get debug shell info...
DebugShellInfo() {
echo "================= DEBUG INFO ================="
printf "🔹 Shell Script Name : %s\n" "$0"
printf "🔹 Declared Interpreter : %s\n" "${SHELL:-<not set>}"
printf "🔹 Bash Version : %s\n" "${BASH_VERSION:-<not bash>}"
# FUNCNAME stack
printf "🔹 FUNCNAME Stack :"
if [[ ${#FUNCNAME[@]} -eq 0 ]]; then
echo " <empty>"
else
echo " ${FUNCNAME[0]}"
for ((i = 1; i < ${#FUNCNAME[@]}; i++)); do
printf " %s\n" "${FUNCNAME[i]}"
done
fi
# BASH_SOURCE stack
printf "🔹 BASH_SOURCE Stack :"
if [[ ${#BASH_SOURCE[@]} -eq 0 ]]; then
echo " <empty>"
else
echo " ${BASH_SOURCE[0]}"
for ((i = 1; i < ${#BASH_SOURCE[@]}; i++)); do
printf " %s\n" "${BASH_SOURCE[i]}"
done
fi
# BASH_LINENO stack
printf "🔹 BASH_LINENO Stack :"
if [[ ${#BASH_LINENO[@]} -eq 0 ]]; then
echo " <empty>"
else
echo " ${BASH_LINENO[0]}"
for ((i = 1; i < ${#BASH_LINENO[@]}; i++)); do
printf " %s\n" "${BASH_LINENO[i]}"
done
fi
echo "=============================================="
}
Now, when I called it, I noticed the following. When it is called while the file is running by double-clicking it outputs...
================= DEBUG INFO =================
🔹 Shell Script Name : C:\Users\***\Desktop\PROGRAMMING\SH STUFF\sigma_sh_lib\tester_copy.sh
🔹 Declared Interpreter : /usr/bin/bash
🔹 Bash Version : 5.2.37(1)-release
🔹 FUNCNAME Stack : DebugShellInfo
MSG
MSG
Main
main
🔹 BASH_SOURCE Stack : /c/Users/***/Desktop/PROGRAMMING/SH STUFF/sigma_sh_lib/lib/utils/debug_shell_info.sh
/c/Users/***/Desktop/PROGRAMMING/SH STUFF/sigma_sh_lib/lib/ui/msg.sh
/c/Users/***/Desktop/PROGRAMMING/SH STUFF/sigma_sh_lib/lib/ui/msg.sh
C:\Users\***\Desktop\PROGRAMMING\SH STUFF\sigma_sh_lib\tester_copy.sh
C:\Users\***\Desktop\PROGRAMMING\SH STUFF\sigma_sh_lib\tester_copy.sh
🔹 BASH_LINENO Stack : 130
1
14
70
0
==============================================
But when it is called with the other ways I mentioned above, it outputs...
================= DEBUG INFO =================
🔹 Shell Script Name : ./tester_copy.sh
🔹 Declared Interpreter : /usr/bin/bash
🔹 Bash Version : 5.2.37(1)-release
🔹 FUNCNAME Stack : DebugShellInfo
MSG
MSG
Main
main
🔹 BASH_SOURCE Stack : /c/Users/***/Desktop/PROGRAMMING/SH STUFF/sigma_sh_lib/lib/utils/debug_shell_info.sh
/c/Users/***/Desktop/PROGRAMMING/SH STUFF/sigma_sh_lib/lib/ui/msg.sh
/c/Users/***/Desktop/PROGRAMMING/SH STUFF/sigma_sh_lib/lib/ui/msg.sh
./tester_copy.sh
./tester_copy.sh
🔹 BASH_LINENO Stack : 194
95
60
70
0
==============================================
Notice the differences in the "Shell Script Name" paths and in "BASH_SOURCE Stack" and "BASH_LINENO Stack" paths!!!
Note: I moved the code of ErrorReport function into a function called MSG.
declare -p BASH_SOURCE FUNCNAME BASH_LINENOtoErrorReport(). That should show the problem. Is the bash version the same everywhere?C:\Users`) with lower line numbers and Linux paths (./tester_copy.sh) with higher numbers makes me wonder if that is a line ending problem (\r\n` being counted as one / two).