Script Execution Methods
Understanding how to execute shell scripts is crucial for effective shell scripting. There are multiple ways to run scripts, each with its own use cases and implications.
Execution Methods Overview
| Method | Syntax | New Process | Environment | Use Case |
|---|---|---|---|---|
| Direct | ./script.sh |
Yes | Inherited | Most common |
| Interpreter | bash script.sh |
Yes | Inherited | Testing/debugging |
| Source | source script.sh |
No | Modified | Environment setup |
| Absolute Path | /path/to/script.sh |
Yes | Inherited | System scripts |
Method 1: Direct Execution
This is the most common way to run scripts.
Prerequisites
# Script must be executable
$ chmod +x myscript.sh
# Script must have proper shebang
$ head -1 myscript.sh
#!/bin/bashExecution
# Run from current directory
$ ./myscript.sh
# Run from anywhere (if in PATH)
$ myscript.shExample Script
#!/bin/bash
# direct_example.sh
echo "Running in process: $$"
echo "Parent process: $PPID"
echo "Current directory: $(pwd)"
export NEW_VAR="Hello from script"Test It
$ chmod +x direct_example.sh
$ ./direct_example.sh
Running in process: 12345
Parent process: 12344
Current directory: /home/user/scripts
# Check if NEW_VAR exists in current shell
$ echo $NEW_VAR
# (empty - variable doesn't exist in parent shell)Method 2: Using Shell Interpreter
Run the script by explicitly calling the shell interpreter.
Bash Interpreter
$ bash myscript.shOther Interpreters
$ sh myscript.sh # POSIX shell
$ zsh myscript.sh # Z shell
$ dash myscript.sh # Debian Almquist shellAdvantages
- No execute permission needed
- Override shebang: Force specific interpreter
- Testing: Test script with different shells
Example
# Create script without execute permission
$ cat > test_interpreter.sh << 'EOF'
#!/bin/bash
echo "Shell: $0"
echo "Bash version: $BASH_VERSION"
EOF
# Run without making executable
$ bash test_interpreter.sh
Shell: bash
Bash version: 5.1.16(1)-release
# Try with different shell
$ sh test_interpreter.sh
Shell: sh
Bash version:Method 3: Source (Dot) Command
Execute script in the current shell environment.
Syntax
$ source myscript.sh
# or
$ . myscript.shKey Characteristics
- No new process: Runs in current shell
- Environment changes persist: Variables and functions remain
- No shebang needed: Uses current shell
- No execute permission needed
Example Script
# source_example.sh
echo "Setting up environment..."
export PROJECT_ROOT="/home/user/myproject"
export PATH="$PROJECT_ROOT/bin:$PATH"
# Define a function
greet() {
echo "Hello from sourced function!"
}
echo "Environment setup complete"
echo "PROJECT_ROOT: $PROJECT_ROOT"Test Sourcing
# Before sourcing
$ echo $PROJECT_ROOT
# (empty)
# Source the script
$ source source_example.sh
Setting up environment...
Environment setup complete
PROJECT_ROOT: /home/user/myproject
# After sourcing - variables persist
$ echo $PROJECT_ROOT
/home/user/myproject
# Function is available
$ greet
Hello from sourced function!Method 4: Absolute Path Execution
Run script using its full path.
Examples
# Full path execution
$ /home/user/scripts/myscript.sh
# Using $HOME variable
$ $HOME/scripts/myscript.sh
# Using tilde expansion
$ ~/scripts/myscript.shUse Cases
- System scripts:
/etc/init.d/apache2 start - Cron jobs: Full paths prevent PATH issues
- Remote execution: SSH with full paths
Method 5: Command Substitution
Execute script and capture output.
Syntax
# Modern syntax
result=$(./myscript.sh)
# Legacy syntax (avoid)
result=`./myscript.sh`Example
# Script that returns a value
$ cat > get_timestamp.sh << 'EOF'
#!/bin/bash
date +%Y%m%d_%H%M%S
EOF
$ chmod +x get_timestamp.sh
# Capture output
$ timestamp=$(./get_timestamp.sh)
$ echo "Backup file: backup_$timestamp.tar.gz"
Backup file: backup_20240115_143022.tar.gzExecution Context and Environment
Process Creation
#!/bin/bash
# process_info.sh
echo "Script PID: $$"
echo "Parent PID: $PPID"
echo "Shell: $0"
ps -f --pid $$ --pid $PPIDEnvironment Inheritance
#!/bin/bash
# env_test.sh
echo "PATH: $PATH"
echo "HOME: $HOME"
echo "USER: $USER"
echo "Custom var: $MY_CUSTOM_VAR"Test Environment
# Set a custom variable
$ export MY_CUSTOM_VAR="test value"
# Run script - inherits environment
$ ./env_test.sh
PATH: /usr/local/bin:/usr/bin:/bin
HOME: /home/user
USER: user
Custom var: test valueScript Arguments and Parameters
Passing Arguments
$ ./myscript.sh arg1 arg2 arg3Accessing Arguments
#!/bin/bash
# args_example.sh
echo "Script name: $0"
echo "First argument: $1"
echo "Second argument: $2"
echo "All arguments: $@"
echo "Number of arguments: $#"Test Arguments
$ ./args_example.sh hello world 123
Script name: ./args_example.sh
First argument: hello
Second argument: world
All arguments: hello world 123
Number of arguments: 3Exit Status and Error Handling
Exit Status
#!/bin/bash
# exit_status.sh
echo "Performing operation..."
# Simulate success or failure
if [ "$1" = "fail" ]; then
echo "Operation failed!"
exit 1
else
echo "Operation successful!"
exit 0
fiCheck Exit Status
$ ./exit_status.sh success
Operation successful!
$ echo $?
0
$ ./exit_status.sh fail
Operation failed!
$ echo $?
1Advanced Execution Techniques
Background Execution
# Run script in background
$ ./long_running_script.sh &
[1] 12345
# Check background jobs
$ jobs
[1]+ Running ./long_running_script.sh &Conditional Execution
# Run second command only if first succeeds
$ ./script1.sh && ./script2.sh
# Run second command only if first fails
$ ./script1.sh || ./script2.sh
# Always run second command
$ ./script1.sh; ./script2.shPiping Script Output
# Pipe script output to another command
$ ./generate_data.sh | sort | uniq
# Redirect output to file
$ ./report_script.sh > report.txt 2>&1Debugging Script Execution
Debug Mode
# Show commands as they execute
$ bash -x myscript.sh
# Or add to script
#!/bin/bash -xVerbose Mode
# Show input lines as they're read
$ bash -v myscript.shSyntax Check
# Check syntax without executing
$ bash -n myscript.shCombined Options
# Multiple debug options
$ bash -xv myscript.shSecurity Considerations
File Permissions
# Secure script permissions
$ chmod 755 myscript.sh # Owner: rwx, Others: r-x
$ chmod 700 myscript.sh # Owner only: rwxPATH Security
#!/bin/bash
# Use absolute paths for security
/bin/ls /home/user
/usr/bin/whoamiInput Validation
#!/bin/bash
# Validate input before execution
if [ $# -ne 1 ]; then
echo "Usage: $0 <filename>"
exit 1
fi
filename="$1"
if [ ! -f "$filename" ]; then
echo "Error: File '$filename' not found"
exit 1
fiBest Practices
1. Always Use Shebang
#!/bin/bash
# or
#!/usr/bin/env bash # More portable2. Set Error Handling
#!/bin/bash
set -euo pipefail # Exit on error, undefined vars, pipe failures3. Use Appropriate Execution Method
- Direct execution: General purpose scripts
- Source: Environment setup scripts
- Interpreter: Testing and debugging
- Background: Long-running processes
4. Handle Arguments Properly
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Usage: $0 <arguments>"
exit 1
fi5. Provide Clear Output
#!/bin/bash
echo "Starting process..."
# ... script logic ...
echo "Process completed successfully"Understanding these execution methods gives you the flexibility to run scripts in the most appropriate way for your specific needs and environment.