Search code examples
bashshellheredoc

Unbound variable


this is a bug I have found nothing about after a relentless search

I'm trying to run a bootstrap file in an EC2 instance, part of an EMR cluster v6.4.0. As the bootstrap action takes longer than 5 minutes, we execute it as a subprocess of the form

#!/bin/bash

var="var"
cat << EOF > ~/bootstrap.sh
intra="intra"
echo $var
echo $intra
EOF
/bin/bash ~/bootstrap.sh
exit 0

But the var "intra" is never set, and the bootstrap action returns the error line n: intra: unbound variable

If you execute that script the "intra" var is not printed. Why can't I assign variables in a subprocess? Thank you!


Solution

  • When using that type of heredoc (<<WORD), you must escape literal $ characters using \$. Same goes for the backtick character (`):

    #!/bin/bash
    var="var"
    cat << EOF > ~/bootstrap.sh
    intra="intra"
    echo $var
    echo \$intra
    EOF
    /bin/bash ~/bootstrap.sh
    exit 0
    

    Another way of generating an equivalent bootstrap script is to use the literal heredoc form <<'WORD':

    #!/bin/bash
    var="var"
    
    # This line will be inserted as-is without variable and subshell expansion:
    cat << 'EOF1' > ~/bootstrap.sh
    intra="intra"
    EOF1
    
    # We will allow this ONE line to expand.
    cat << EOF2 >> ~/bootstrap.sh
    echo $var
    EOF2
    
    # Back to literal insertions, no escaping necessary.
    cat << 'EOF3' >> ~/bootstrap.sh
    echo $intra
    EOF3
    /bin/bash ~/bootstrap.sh
    exit 0
    

    Inspecting the contents of ~/bootstrap.sh is a good place to start debugging.