此处文档在 shell 中的工作原理
How here document works in shell
在进行输入重定向时,shell 打开文件描述符为 0 的 '<' 右侧的文件,但是在 heredoc 的情况下没有这样的文件可以打开,我是想知道 shell 在这种情况下到底做了什么。
cat > file.txt << EOF
line1
line2
EOF
直到 bash 5.1
,它将 here-document 的内容复制到一个临时文件,然后将输入重定向到该文件。
从 5.1 开始,这取决于 here-document 的大小。如果它适合管道缓冲区,它会创建一个管道并将 here-document 的内容写入管道。如果它太大了,它会恢复到临时文件方法。
在 bash 5.0 及更早版本中,它会创建一个临时文件,写入 heredoc 内容,然后将该文件重定向到标准输入。
我们可以在显示系统调用的 strace
中看到这种情况。以下是用内联注释注释的相关部分:
$ 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
在进行输入重定向时,shell 打开文件描述符为 0 的 '<' 右侧的文件,但是在 heredoc 的情况下没有这样的文件可以打开,我是想知道 shell 在这种情况下到底做了什么。
cat > file.txt << EOF
line1
line2
EOF
直到 bash 5.1
,它将 here-document 的内容复制到一个临时文件,然后将输入重定向到该文件。
从 5.1 开始,这取决于 here-document 的大小。如果它适合管道缓冲区,它会创建一个管道并将 here-document 的内容写入管道。如果它太大了,它会恢复到临时文件方法。
在 bash 5.0 及更早版本中,它会创建一个临时文件,写入 heredoc 内容,然后将该文件重定向到标准输入。
我们可以在显示系统调用的 strace
中看到这种情况。以下是用内联注释注释的相关部分:
$ 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