You're redirecting tee
's input, not bash
's. Use:
bash << EOF | tee foo
echo Hello
EOF
A few more examples to illustrate how it works:
bash << EO1 3<< EO\2 | tee 3<< EO3 foo 4<< EO4
fed (as a deleted temp file open in read-only mode) to bash fd 0
EO1
fed to bash fd 3 without $variable and $(cmd) expansion
EO2
fed to tee fd 3
(not that tee does anything with its fd 3)
EO3
fed to tee fd 4
(see how, like any redirection operator 3<< END can appear anywhere on
the command line (for simple commands at least))
EO4
Redirecting compound commands:
{ head -n2; wc -l; } << EOF
fed as fd 0 for the whole command group
$(ps -e)
EOF
Or:
if head -n1; then
head -n2
fi << EOF
1
2
3
EOF
You can reuse the same ending token:
$ ls -l /proc/self/fd << E 3<< E >&2 | 3<< E 4<< E ls -l /proc/self/fd
pipe heredoc> E
pipe heredoc> E
pipe heredoc> E
pipe heredoc> E
total 0
lr-x------ 1 stephane stephane 64 Feb 24 12:50 0 -> /tmp/zshLiVzp3 (deleted)
lrwx------ 1 stephane stephane 64 Feb 24 12:50 1 -> /dev/pts/5
lrwx------ 1 stephane stephane 64 Feb 24 12:50 2 -> /dev/pts/5
lr-x------ 1 stephane stephane 64 Feb 24 12:50 3 -> /tmp/zshFLbQ7T (deleted)
lr-x------ 1 stephane stephane 64 Feb 24 12:50 4 -> /proc/25749/fd/
total 0
lr-x------ 1 stephane stephane 64 Feb 24 12:50 0 -> pipe:[70735808]
lrwx------ 1 stephane stephane 64 Feb 24 12:50 1 -> /dev/pts/5
lrwx------ 1 stephane stephane 64 Feb 24 12:50 2 -> /dev/pts/5
lr-x------ 1 stephane stephane 64 Feb 24 12:50 3 -> /tmp/zshL3KBp3 (deleted)
lr-x------ 1 stephane stephane 64 Feb 24 12:50 4 -> /tmp/zshcJjS7T (deleted)
lr-x------ 1 stephane stephane 64 Feb 24 12:50 5 -> /proc/25748/fd/
As to why the first history
command is run in that new bash
in:
$ bash | tee foo <<EOF
echo Hello
EOF
$ history
$ history
1 ...
That is because bash
stdin is still the terminal, but its stdout is a dead pipe (at the other end of the pipe, tee
has redirected its stdin from that delete temp file, so the reading end of that pipe is closed).
bash
doesn't write its prompt or the echo of what you type on its stdout (the dead pipe), but to the terminal, so that bash
will let you enter history
at a first prompt.
However, that history
(which is a builtin, so executed by the bash
process, not a child), will write its output to that dead pipe. When doing so, the bash
process will receive a SIGPIPE signal (since there's no reader) and die.
The next prompt will be issued by the calling shell.
Just use redirection operator >
at the first line:
sqlplus -s "/nolog" <<EOF >logfile
conn / as sysdba
@?/sqlpatch/19282021/postinstall.sql
exit;
EOF
You can also write >logfile
at the beginning of the line, what is equally legal syntax in most shells, but less commonly practiced.
>logfile sqlplus -s "/nolog" <<EOF
conn / as sysdba
@?/sqlpatch/19282021/postinstall.sql
exit;
EOF
Best Answer
There are multiple ways to do this. The simplest is probably this:
Another, which is nicer syntax in my opinion:
This works as well, but without the subshell:
More variations:
Or:
By the way, I expect the use of
cat
in your question is a placeholder for something else. If not, take it out, like this:Which could be simplified to this:
or:
Redirecting output instead of piping
Using
cat
to get the equivalent ofecho test > out
:Multiple Here Documents
This produces the output:
Here's what's going on:
( ... )
and runs the enclosed commands in a subshell.cat <&3
says to run cat with file descriptor (fd) 0 (stdin) redirected from fd 3; in other words, cat out the input from fd 3.(...)
is started, the shell sees the two here document redirects and substitutes fd 0 (<<EOF
) and fd 3 (3<<EOF2
) with the read-side of pipes