'How here document works in shell

While doing the input redirection, the shell opens the file on the right side of '<' with file descriptor 0, but in the case of the heredoc there is no such file to open, I am wondering what exactly shell does in this case.

cat > file.txt << EOF
line1
line2
EOF


Solution 1:[1]

In bash 5.0 and older, it creates a temporary file, writes the heredoc contents, and then redirects that file to stdin.

We can see this happen with strace, which shows syscalls. Here are the relevant portions annotated with inline comments:

$ strace -f bash -c $'cat > file.txt << EOF\nline1\nline2\nEOF'

# Open a temporary file `/tmp/sh-thd-1641928925`.
[pid  8292] open("/tmp/sh-thd-1641928925", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3

# Write the heredoc contents to the file.
[pid  8292] dup(3)                      = 4
[pid  8292] write(4, "line1\nline2\n", 12) = 12
[pid  8292] close(4)                    = 0

# Open the file read-only.
[pid  8292] open("/tmp/sh-thd-1641928925", O_RDONLY) = 4

# Close the original file and unlink it so there's no filesystem
# reference. The file will be fully deleted once all fds are closed.
[pid  8292] close(3)                    = 0
[pid  8292] unlink("/tmp/sh-thd-1641928925") = 0

# Redirect the file to stdin.
[pid  8292] dup2(4, 0)                  = 0
[pid  8292] close(4)                    = 0

# Execute `cat`.
[pid  8292] execve("/usr/bin/cat", ["cat"], 0x187c160 /* 113 vars */) = 0

Solution 2:[2]

Until bash 5.1, it copies the contents of the here-document to a temporary file, then redirects input to that file.

Since 5.1, it depends on how large the here-document is. If it fits into the pipe buffer, it creates a pipe and writes the contents of the here-document to the pipe. If it's too large for this, it reverts to the temporary file method.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2