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
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