Problem with here-document not seeing delimiter

System is Oracle Linux 6 (derivative of RHEL)
Given this script (copied from vi with line numbering for reference)

  1 #!/bin/sh
  2 ORAENV_ASK=NO
  3 echo "*****************************************************"
  4 echo "**    Stop all databases and listener"
  5 echo "*****************************************************"
  6 egrep -i '^hr9|^fs9' /etc/oratab |\
  7    awk -F\: '{print $1}'|\
  8 while read ORACLE_SID
  9 do
 10    echo processing $ORACLE_SID
 11    source oraenv
 12    sqlplus / as sysdba <<EOF
 13    shutdown
 14 EOF
 15 done
 16 lsnrctl stop

Complains about the here-document:

oracle:$ ./stop_all.sh
*****************************************************
**    Stop all databases and listener
*****************************************************
./stop_all.sh: line 16: warning: here-document at line 12 delimited by end-of-file (wanted `EOF')
./stop_all.sh: line 17: syntax error: unexpected end of file

2018-06-28 10:24:02
oracle:$ 

Any invisible characters in that script?

Put a dash character in the first EOF: <<-EOF
Other than removing non-printing characters this helps the problem you seem to have.

per: An Introduction to Linux Shell Scripting for DBAs

PS: /bin/sh is the bourne shell for oracle linux. I think it is supposed to be POSIX-compliant, Don Cragun might know.

I considered non-printing characters, but when I put vi into hex mode to investigate I found nothing amiss. Just EOL (x'0A') where they should be.

0000000: 2321 2f62 696e 2f73 680a 4f52 4145 4e56  #!/bin/sh.ORAENV
0000010: 5f41 534b 3d4e 4f0a 6563 686f 2022 2a2a  _ASK=NO.echo "**
0000020: 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a  ****************
0000030: 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a  ****************
0000040: 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a  ****************
0000050: 2a2a 2a22 0a65 6368 6f20 222a 2a20 2020  ***".echo "**
0000060: 2053 746f 7020 616c 6c20 6461 7461 6261   Stop all databa
0000070: 7365 7320 616e 6420 6c69 7374 656e 6572  ses and listener
0000080: 220a 6563 686f 2022 2a2a 2a2a 2a2a 2a2a  ".echo "********
0000090: 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a  ****************
00000a0: 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a  ****************
00000b0: 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a22 0a65  *************".e
00000c0: 6772 6570 202d 6920 275e 6872 397c 5e66  grep -i '^hr9|^f
00000d0: 7339 2720 2f65 7463 2f6f 7261 7461 6220  s9' /etc/oratab
00000e0: 7c5c 0a20 2020 6177 6b20 2d46 5c3a 2027  |\.   awk -F\: '
00000f0: 7b70 7269 6e74 2024 317d 277c 5c0a 7768  {print $1}'|\.wh
0000100: 696c 6520 7265 6164 204f 5241 434c 455f  ile read ORACLE_
0000110: 5349 440a 646f 0a20 2020 6563 686f 2070  SID.do.   echo p
0000120: 726f 6365 7373 696e 6720 244f 5241 434c  rocessing $ORACL
0000130: 455f 5349 440a 2020 2073 6f75 7263 6520  E_SID.   source
0000140: 6f72 6165 6e76 200a 2020 2073 716c 706c  oraenv .   sqlpl
0000150: 7573 202f 2061 7320 7379 7364 6261 203c  us / as sysdba <
0000160: 3c2d 454f 460a 2020 2020 2073 6875 7464  <-EOF.     shutd
0000170: 6f77 6e0a 454f 4620 2020 0a64 6f6e 650a  own.EOF   .done.
0000180: 6c73 6e72 6374 6c20 7374 6f70 0a         lsnrctl stop.

With the suggested hyphen, no joy:

oracle:$ cat stop_all.sh
#!/bin/sh
ORAENV_ASK=NO
echo "*****************************************************"
echo "**    Stop all databases and listener"
echo "*****************************************************"
egrep -i '^hr9|^fs9' /etc/oratab |\
   awk -F\: '{print $1}'|\
while read ORACLE_SID
do
   echo processing $ORACLE_SID
   source oraenv
   sqlplus / as sysdba <<EOF
     shutdown
EOF
done
lsnrctl stop

2018-06-28 14:10:51
oracle:$ ./stop_all.sh
*****************************************************
**    Stop all databases and listener
*****************************************************
./stop_all.sh: line 16: warning: here-document at line 12 delimited by end-of-file (wanted `EOF')
./stop_all.sh: line 17: syntax error: unexpected end of file

2018-06-28 14:10:55
oracle:$

There you are - EOF with three trailing spaces! Try without.

3 Likes

Out of desperation, I tried re-typing the entire script from scratch - no copy and paste. This time it worked. :confused:

---------- Post updated 06-29-18 at 08:25 AM ---------- Previous update was 06-28-18 at 02:41 PM ----------

Well, I learned something today. I knew that the EOF had to be at the beginning of the line (immediately following x'0a', but never knew that it was also sensitive to trailing spaces. Thanks for catching that.

1 Like

The Bourne shell is not a POSIX-compliant shell. The shell specified by the POSIX standard was based on the Bourne shell with some Korn shell changes and extensions.

/bin/sh on most Linux systems is a bash or dash shell with options set so that it is intended to act like a POSIX-compliant shell, but is not tested to conform to POSIX requirements by any POSIX or UNIX conformance test suite.

A here-document has two things that control how it works. In the form:

command <<word
contents
delimiter

where no part of word is quoted, the input fed into command is the result of performing parameter expansions, command substitutions, and arithmetic expansions on contents . If any part of word is quoted, the input fed into command is contents . The end of contents is identified by a line containing exactly the contents of delimiter immediately followed by a <newline> character where delimiter is word after quote removal has been applied.

In the form:

command <<-word
contents
delimiter

all leading <tab> characters in each line of contents and in the terminating line containing delimiter are discarded before the actions mentioned above are applied. (Note that it is just leading <tab>s; not leading <tab>s and/or <space>s.)