How to Enable Command Echoing in Bash Scripts: Print Commands Before Execution


2 views

```html

How to Enable Command Echoing in Bash Scripts

By default, bash scripts execute commands without displaying them in the terminal output. For debugging or logging purposes, you might want to see each command before it's executed.

#!/bin/bash
cd ~/project
ls -la

The most straightforward way is to use the set -x command at the beginning of your script:

#!/bin/bash
set -x
cd ~/project
ls -la

This will produce output like:

+ cd ~/project
+ ls -la

You can also enable tracing directly in the shebang line:

#!/bin/bash -x
cd ~/project
ls -la

To enable tracing for specific sections only:

#!/bin/bash
# Normal execution
cd ~/project

# Enable tracing
set -x
ls -la
complex_command
set +x

# Back to normal execution
another_command

Customize the trace output prefix using PS4:

#!/bin/bash
export PS4='+ ${BASH_SOURCE}:${LINENO}: '
set -x
cd ~/project
ls -la

Here's a more complete example showing how this works in a real script:

#!/bin/bash -x

# Configuration
LOG_DIR="/var/log/myapp"
CONFIG_FILE="/etc/myapp.conf"

# Create log directory if not exists
[ -d "$LOG_DIR" ] || mkdir -p "$LOG_DIR"

# Verify config exists
if [ ! -f "$CONFIG_FILE" ]; then
    echo "Config file missing" >&2
    exit 1
fi

# Process config
source "$CONFIG_FILE"
  • Debugging complex scripts
  • Understanding script flow during development
  • Creating verbose logs for auditing
  • Troubleshooting scripts run by other users
  1. Use set -x temporarily during debugging
  2. Consider removing it before production deployment
  3. Combine with set -e for better error handling
  4. Use selective tracing for large scripts

When debugging bash scripts or demonstrating script behavior, it's often helpful to see each command before it executes. This is particularly useful in:

  • Debugging complex scripts
  • Documenting script execution flow
  • Teaching bash scripting concepts
  • Auditing script behavior

The simplest way to enable command echoing is by using the -x option:

#!/bin/bash -x
cd ~/hello
ls

Alternatively, you can set it within the script:

#!/bin/bash
set -x  # Enable command echoing
cd ~/hello
ls
set +x  # Disable command echoing

The PS4 variable controls the prompt prefix for traced commands. Customize it for better debugging:

#!/bin/bash
PS4='+ $BASH_SOURCE:$LINENO: '
set -x
cd ~/hello
ls

For finer control over which commands get echoed:

#!/bin/bash
echo "About to change directory" >&2
cd ~/hello || exit 1

# Only echo the ls command
(set -x; ls)

echo "Done listing contents" >&2

For comprehensive debugging, combine with other options:

#!/bin/bash
set -exo pipefail
# -e: Exit on error
# -x: Print commands
# -o pipefail: Catch pipeline errors
cd ~/hello || exit 1
ls | wc -l

Here's how this applies to a practical build script:

#!/bin/bash -x
# Build and deploy script with full tracing

BUILD_DIR="dist"
SRC_DIR="src"

clean() {
  rm -rf "$BUILD_DIR"
}

build() {
  mkdir -p "$BUILD_DIR"
  cp -r "$SRC_DIR"/* "$BUILD_DIR/"
  minify "$BUILD_DIR"/*.js
}

deploy() {
  scp -r "$BUILD_DIR" user@server:/var/www/
}

clean
build
deploy
  • Use set -x temporarily during debugging
  • Consider adding a debug flag to your scripts: [[ $DEBUG ]] && set -x
  • Redirect trace output to stderr: exec 2>&1
  • Be mindful of sensitive information in echoed commands

If command echoing isn't working as expected:

  1. Check if another part of the script uses set +x
  2. Verify the script has execute permissions
  3. Ensure you're not redirecting stderr where traces go