Bird
Raised Fist0
Bash Scriptingscripting~10 mins

Debugging with PS4 in Bash Scripting - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Debugging with PS4
Set PS4 variable
↓
Enable debugging with 'set -x'
↓
Run script commands
↓
Each command prints with PS4 prefix
↓
Observe output with debug info
↓
Disable debugging with 'set +x'
↓
Script continues normally
Set PS4 to customize debug output prefix, enable debugging with 'set -x', run commands to see debug info, then disable debugging.
Execution Sample
Bash Scripting
PS4='+ $BASH_SOURCE:$LINENO:${FUNCNAME[0]}: '
set -x
myfunc() {
  echo "Hello"
}
myfunc
set +x
This script sets PS4 to show file, line, and function name before each command, enables debugging, runs a function, then disables debugging.
Execution Table
StepCommand RunPS4 Prefix OutputDebug OutputNotes
1PS4='+ $BASH_SOURCE:$LINENO:${FUNCNAME[0]}: 'Set PS4 variable for debug prefix
2set -xEnable debugging mode
3myfunc() {+ script.sh:3:: myfunc() {Start function definition
4 echo "Hello"+ script.sh:4:: echo "Hello"During function definition: echo command
5}+ script.sh:5:: }End function definition
6myfunc+ script.sh:7:: myfuncCall function
7echo "Hello"+ script.sh:4:myfunc: HelloFunction prints Hello
8set +x+ script.sh:8:: set +xDisable debugging mode
9Debugging off, normal script continues
💡 Debugging stops after 'set +x', script runs normally without debug output.
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 8Final
PS4default+ $BASH_SOURCE:$LINENO:${FUNCNAME[0]}: + $BASH_SOURCE:$LINENO:${FUNCNAME[0]}: + $BASH_SOURCE:$LINENO:${FUNCNAME[0]}: + $BASH_SOURCE:$LINENO:${FUNCNAME[0]}:
set -x (debug mode)offoffonoffoff
Key Moments - 3 Insights
Why does each debug line start with the PS4 prefix?
Because PS4 defines the prefix shown before each command when debugging is enabled with 'set -x', as seen in execution_table rows 3-7.
What happens if we don't disable debugging with 'set +x'?
Debug output continues for all commands, cluttering output. Execution_table row 9 shows debugging stops after 'set +x'.
Why does the function name appear in the PS4 prefix during the function call?
Because PS4 uses ${FUNCNAME[0]} which shows the current function name, visible in row 7 of execution_table.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the PS4 prefix output when the echo command inside the function runs?
A+ script.sh:4:myfunc:
B+ script.sh:7::
C+ script.sh:3::
D+ script.sh:8::
💡 Hint
Check execution_table row 7 under 'PS4 Prefix Output' column.
At which step does debugging get disabled?
AStep 2
BStep 6
CStep 8
DStep 9
💡 Hint
Look at execution_table row 8 where 'set +x' is run.
If PS4 was set to just '+ ', how would the debug output prefix change?
AIt would show file and line number before each command
BIt would show only '+ ' before each command
CIt would show function name only
DNo debug output would appear
💡 Hint
PS4 defines the prefix; changing it to '+ ' removes file, line, and function info.
Concept Snapshot
PS4 sets the prefix for debug output in bash.
Use 'set -x' to enable debugging and see commands with PS4 prefix.
Use 'set +x' to disable debugging.
PS4 can include variables like $BASH_SOURCE, $LINENO, ${FUNCNAME[0]}.
This helps trace script execution step-by-step.
Full Transcript
Debugging with PS4 in bash means setting the PS4 variable to customize the prefix shown before each command when debugging is enabled. You enable debugging with 'set -x', which prints each command with the PS4 prefix before running it. This helps you see exactly what the script is doing and where. You can include file name, line number, and function name in PS4 for detailed tracing. When done, disable debugging with 'set +x' to stop the extra output. This method helps find errors by showing the script's flow clearly.

Practice

(1/5)
1. What does the PS4 variable control in a bash script when debugging?
easy
A. The number of commands to debug before stopping
B. The output file where debug logs are saved
C. The timeout duration for debugging
D. The prefix shown before each command when debugging is enabled

Solution

  1. Step 1: Understand the role of PS4 in bash debugging

    PS4 sets the prefix string that appears before each command when debugging with set -x is active.
  2. Step 2: Differentiate PS4 from other debugging settings

    PS4 does not control output files, timeouts, or command counts; it only changes the debug output prefix.
  3. Final Answer:

    The prefix shown before each command when debugging is enabled -> Option D
  4. Quick Check:

    PS4 = debug output prefix [OK]
Hint: PS4 sets what you see before each debug command line [OK]
Common Mistakes:
  • Confusing PS4 with output file settings
  • Thinking PS4 controls debug duration
  • Assuming PS4 limits number of debug commands
2. Which of the following is the correct way to set a custom PS4 prefix to show the current line number in bash debugging?
easy
A. PS4='Line \$LINENO: '
B. PS4='Line $LINENO: '
C. PS4='Line \n: '
D. PS4='Line $LINENO\n'

Solution

  1. Step 1: Understand variable expansion in PS4

    To show the current line number dynamically, you must escape the dollar sign in PS4 so it expands at runtime, not when assigned.
  2. Step 2: Identify correct escaping

    Using PS4='Line \$LINENO: ' escapes the dollar sign, so $LINENO expands during debugging, showing the actual line number.
  3. Final Answer:

    PS4='Line \$LINENO: ' -> Option A
  4. Quick Check:

    Escape $ for runtime expansion in PS4 [OK]
Hint: Escape $ in PS4 to expand variables during debugging [OK]
Common Mistakes:
  • Not escaping $ causes literal $LINENO output
  • Using \n instead of $LINENO for line number
  • Placing newline characters incorrectly
3. Given this script snippet with debugging enabled:
PS4='+ $BASH_SOURCE:$LINENO:'
set -x
x=5
y=10
z=$((x + y))
set +x

What is the first debug output line shown after set -x?
medium
A. + script.sh:2: x=5
B. + : x=5
C. + :2: x=5
D. + script.sh:x=5

Solution

  1. Step 1: Analyze PS4 value and variable expansion

    PS4 is set to '+ $BASH_SOURCE:$LINENO:' but $BASH_SOURCE and $LINENO are not escaped, so they expand immediately when assigned, likely empty or current shell values.
  2. Step 2: Determine actual debug prefix

    Because variables are not escaped, $BASH_SOURCE is empty and $LINENO is 2 (line of set -x), so prefix becomes '+ :2:'.
  3. Final Answer:

    + :2: x=5 -> Option C
  4. Quick Check:

    Unescaped vars expand early, prefix = '+ :2:' [OK]
Hint: Unescaped vars in PS4 expand immediately, not during debug [OK]
Common Mistakes:
  • Assuming $BASH_SOURCE expands to script filename
  • Expecting line number to be dynamic without escaping
  • Ignoring immediate expansion on assignment
4. You wrote this script to debug with line numbers:
PS4='Line $LINENO: '
set -x
foo=bar
set +x

But the debug output shows Line $LINENO: foo=bar literally. What is the fix?
medium
A. Change PS4 to 'Line \$LINENO: ' to delay variable expansion
B. Remove quotes around PS4 assignment
C. Use single quotes instead of double quotes for PS4
D. Set PS4 after set -x

Solution

  1. Step 1: Identify why $LINENO is literal

    Using single quotes with unescaped $LINENO causes it to be treated as literal text, not expanded during debugging.
  2. Step 2: Fix by escaping $ for runtime expansion

    Escaping $ as \$ in PS4 delays expansion until debugging runs, showing actual line numbers.
  3. Final Answer:

    Change PS4 to 'Line \$LINENO: ' to delay variable expansion -> Option A
  4. Quick Check:

    Escape $ in PS4 to expand at debug time [OK]
Hint: Escape $ in PS4 to see line numbers during debugging [OK]
Common Mistakes:
  • Not escaping $ in PS4
  • Changing quotes incorrectly
  • Setting PS4 after enabling debugging
5. You want to debug a bash script showing the filename, line number, and function name before each command. Which PS4 setting achieves this correctly?
hard
A. PS4='+ ${BASH_SOURCE}:${LINENO}:${FUNCNAME[0]}: '
B. PS4='+ \${BASH_SOURCE}:\${LINENO}:\${FUNCNAME[0]}: '
C. PS4='+ $BASH_SOURCE:$LINENO:$FUNCNAME: '
D. PS4='+ \$BASH_SOURCE:\$LINENO:\$FUNCNAME: '

Solution

  1. Step 1: Understand variable expansion timing in PS4

    To show dynamic info like filename, line number, and function name during debugging, variables must be escaped with backslashes to delay expansion until debug time.
  2. Step 2: Choose correct syntax for array variable FUNCNAME

    Use \${FUNCNAME[0]} to get current function name properly escaped.
  3. Step 3: Verify full PS4 string

    PS4='+ \${BASH_SOURCE}:\${LINENO}:\${FUNCNAME[0]}: ' correctly escapes all variables and uses braces for array indexing, ensuring dynamic debug info appears.
  4. Final Answer:

    PS4='+ \${BASH_SOURCE}:\${LINENO}:\${FUNCNAME[0]}: ' -> Option B
  5. Quick Check:

    Escape all vars with braces for dynamic debug info [OK]
Hint: Escape variables with braces in PS4 for dynamic debug info [OK]
Common Mistakes:
  • Not escaping variables causing static output
  • Missing braces for array FUNCNAME
  • Using $FUNCNAME without index for function name
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard