When working with bash scripts on Solaris 11, you might encounter a situation where environment variables set within a script don't persist after the script finishes execution. This occurs despite using the export
command correctly.
Here's a fundamental Unix principle at play:
#!/usr/bin/bash
TEST="value_to_persist"
export TEST
The script above runs in its own subshell, and any environment changes are confined to that subshell. When the script terminates, the subshell and its environment are destroyed.
1. Sourcing the Script
Instead of executing the script, source it:
source ./script.sh
# or
. ./script.sh
2. Using Environment Files
Create an environment file and load it:
# In script.sh
echo "export TEST=persisted_value" > /tmp/env_vars
# In parent shell
source /tmp/env_vars
3. Command Substitution
For simple variable assignments:
eval $(echo "TEST=persisted_value")
Solaris 11's default shell might be different from what you expect. Always verify:
# Check your current shell
echo $SHELL
# Explicitly use bash
#!/usr/bin/bash
Add these checks to your script:
#!/usr/bin/bash
echo "Parent PID: $PPID"
echo "Current PID: $$"
export TEST=debug_value
env | grep TEST
When working with bash scripts, it's crucial to understand that child processes (including scripts) cannot modify their parent process's environment. This is by Unix design - each process maintains its own environment space. Here's what's happening in your example:
# Parent shell
$ TEST="parent_value" # Sets variable in parent shell
$ ./test.sh # Child process starts
# Inside test.sh:
TEST="child_value" # Only modifies child's environment
exit # Child terminates, environment discarded
# Back in parent shell
$ echo $TEST # Still shows "parent_value"
Let's examine a more comprehensive test case showing the scope boundaries:
#!/bin/bash
# script_scope_demo.sh
# Initial state
echo "Script start - TEST value: ${TEST:-unset}"
# Local assignment
TEST="script_local"
echo "After local assignment: $TEST"
# Export attempt
export TEST="script_exported"
echo "After export: $TEST"
# Function call demonstrating same behavior
nested_function() {
TEST="function_value"
echo "Inside function: $TEST"
}
nested_function
echo "After function: $TEST"
# End of script - all changes disappear
If you need to modify the parent shell's environment, consider these approaches:
# Method 1: Sourcing the script
$ source ./test.sh # or equivalently: . ./test.sh
# Variables will persist because script runs in current shell
# Method 2: Explicit evaluation
$ eval "$(./env_generator.sh)"
# Where env_generator.sh outputs 'export' commands
# Method 3: Temporary environment file
#!/bin/bash
# set_env.sh
echo "export TEST=$(date +%s)" > /tmp/myenv
# Then in parent shell:
$ source /tmp/myenv
For complex cases where you need to maintain environment changes across multiple script invocations:
#!/bin/bash
# env_manager.sh
# Preserve existing environment
ENV_FILE="${ENV_FILE:-/tmp/current_env}"
trap 'export -p > "$ENV_FILE"' EXIT
# Your script logic here
if [[ -f "$ENV_FILE" ]]; then
source "$ENV_FILE"
fi
# Make modifications
export LAST_RUN="$(date)"
export COUNTER=$(( ${COUNTER:-0} + 1 ))
Use these commands to inspect environment behavior:
# Show all exported variables
$ export -p
# Check if specific variable is exported
$ declare -p TEST
# Compare parent and child environments
$ env > parent_env.txt
$ bash -c 'env' > child_env.txt
$ diff parent_env.txt child_env.txt