将脚本输送到 bash 中?

Rob*_*ell 2 bash shell

是否有区别:

$ bash ~/script.sh
Run Code Online (Sandbox Code Playgroud)

和:

$ cat ~/script.sh | bash
Run Code Online (Sandbox Code Playgroud)

他们的行为似乎略有不同,我无法弄清楚发生了什么。我script.sh的 bash 包含多行,但是当我将其通过管道传输到 bash 时它似乎提前中止(但是当我直接运行脚本时它会运行到完成)。

这两种方式运行脚本有什么区别?

此外,当我使用 时<,行为与第一个示例相同(运行至完成):

bash <( ~/script.sh )
Run Code Online (Sandbox Code Playgroud)

该脚本是沿着

set -eux
ssh CLUSTER_0_SERVER_0 "do_something" || ssh CLUSTER_0_SERVER_1 "do_something"
ssh CLUSTER_1_SERVER_0 "do_something" || ssh CLUSTER_1_SERVER_1 "do_something"
Run Code Online (Sandbox Code Playgroud)

Mih*_*eac 5

您运行相同脚本的方式在语义上都不同。

例如,请参阅这个简单的脚本:

#!/bin/bash
echo $$
ssh 127.0.0.1
echo $$
Run Code Online (Sandbox Code Playgroud)

直接运行它将执行其中的所有行,并且两次echo调用都将打印相同的 PID:一切都是一个进程,它一个接一个地运行脚本中的命令。

运行它 via 一开始cat ./script.sh | bash会创建两个不同的进程:一个用于执行 the cat,另一个用于bash. 但是,当 bash 解释器读取并执行ssh命令时,您会收到错误消息(如果 ssh 未配置为不打印它):

Pseudo-terminal will not be allocated because stdin is not a terminal
Run Code Online (Sandbox Code Playgroud)

然后你登录到机器,它立即离开,杀死当前进程。因此,第二个值是不同的 PID。在您的情况下,您有两个ssh由条件运算符链接的命令。然而,因为在第一个解释器被杀死后,第二个命令将无法执行。这就是为什么你只会得到*_SERVER_0 ssh执行的命令。

第三种情况有效,但只是错误。所述<( cmd )构建体的装置执行cmd并通过其输出作为一个文件参数给调用者。在您的情况下,脚本不会打印任何内容,因此您看不到任何错误。运行示例脚本,你会得到如下错误:

/dev/fd/63: line 1: 29355: command not found
Run Code Online (Sandbox Code Playgroud)

第四种情况(在评论中建议)bash < scriptcat script | bash.

运行 bash 脚本的正确方法是通过bash script./script(和shebang)。如果您想在同一进程中运行指令,您也可以使用. script( source) 所有其他的可能有效或无效,这取决于一些幸运的副作用(通常它们不应该起作用)。