mbi*_*ras 4 command-line bash here-document ansible
我很好奇 heredocs 如何作为文件传递给命令行实用程序背后的理论。
最近,我发现我可以将文件作为 heredoc 传递。
例如:
awk '{ split($0, arr, " "); print arr[2] }' <<EOF
foo bar baz
EOF
bar
Run Code Online (Sandbox Code Playgroud)
出于以下几个原因,这对我来说是有利的:
例如:
ruby <<EOF
puts "'hello $HOME'"
EOF
'hello /Users/mbigras'
ruby <<'EOF'
puts "'hello $HOME'"
EOF
'hello $HOME'
Run Code Online (Sandbox Code Playgroud)
我不清楚发生了什么。似乎shell认为heredoc是一个内容等于heredoc值的文件。我已经将这种技术与 cat 一起使用,但我仍然不确定发生了什么:
cat <<EOL
hello world
EOL
hello world
Run Code Online (Sandbox Code Playgroud)
我知道cat
打印文件的内容,所以大概这个 heredoc 是某种临时文件。
当我“将heredoc传递给命令行程序”时,我对究竟发生了什么感到困惑。
这是使用ansible-playbook的示例。我将实用程序作为 heredoc 传递给剧本;但是它失败了,如使用所示echo $?
:
ansible-playbook -i localhost, -c local <<EOF &>/dev/null
---
- hosts: all
gather_facts: false
tasks:
- name: Print something
debug:
msg: hello world
EOF
echo $?
5
Run Code Online (Sandbox Code Playgroud)
但是,如果我通过该实用程序相同的 heredoc 但在它/dev/stdin
之前成功
ansible-playbook -i localhost, -c local /dev/stdin <<EOF &>/dev/null
---
- hosts: all
gather_facts: false
tasks:
- name: Print something
debug:
msg: hello world
EOF
echo $?
0
Run Code Online (Sandbox Code Playgroud)
ansible-playbook
失败而第二个版本成功?/dev/stdin
在heredoc之前通过有什么意义?ruby
或awk
不需要/dev/stdin
在 heredoc 之前?当一个人“将heredoc作为文件传递”时究竟发生了什么?
你不是。Here-documents 提供标准输入,就像一个管道。你的榜样
awk '{ ... }' <<EOF
foo bar baz
EOF
Run Code Online (Sandbox Code Playgroud)
完全等同于
echo foo bar baz | awk '{ ... }'
Run Code Online (Sandbox Code Playgroud)
awk
, cat
, 和ruby
所有从标准输入读取,如果它们没有在命令行上读取的文件名。这是一个实现选择。
为什么带有 anisble-playbook 的第一个版本失败而第二个版本成功?
ansible-playbook
默认情况下不从标准输入读取,而是需要文件路径。这是一种设计选择。
/dev/stdin
很可能是指向 的符号链接/dev/fd/0
,这是一种谈论当前进程的文件描述符#0(标准输入)的方式。这是您的内核(或系统库)公开的内容。该ansible-playbook
命令/dev/stdin
像常规文件系统文件一样打开并最终读取它自己的标准输入,否则这些输入将被忽略。
您可能也有/dev/stdout
和/dev/stderr
链接的FD 1&2,你可以,如果你使用,以及在告诉一些地方把它的输出。
在heredoc之前传递/dev/stdin有什么意义?
它是ansible-playbook
命令的参数。
为什么像 ruby 或 awk 这样的其他实用程序在 heredoc 之前不需要 /dev/stdin?
默认情况下,它们从标准输入中读取作为设计选择,因为它们是为在管道中使用而设计的。他们出于同样的原因写入标准输出。