理解“流程替代”的概念

理解“流程替代”的概念

我寻求对针对普通受众/非专业系统管理员的术语“进程替代”的简单解释,他们偶尔为个人项目进行服务器环境维护,而不是每天为客户或公司进行服务器环境维护,如果可以在这里提出要求的话。

  • 发明这个概念是为了解决什么问题
  • 什么流程被取代以及被什么取代(名称可能会产生误导)?
  • 它也被命名为“保留标准输入”吗?如果是的话为什么?如果 stdin 设备保存可以通过管道传输到另一个命令的标准输入,那么还有什么可以“保留”呢?

这可能有助于我理解以下命令:

bash <(wget -O - URL)

新人注意事项: -O -告诉wget将数据写入标准输出;

答案1

重要事实:涉及两个 shell

首先请注意涉及两个 shell。您在其中工作的外部 Bash,您bash <(wget -O - URL)在其中调用(键入)。当命令执行时,内部 Bash 作为外部 Bash 的子进程运行。

换句话说,外部 Bash 接受bash <(wget -O - URL)命令并生成内部 Bash。我将在适当的情况下区分两者。


重要事实:使用 Bash 运行代码的方法不止一种

有几种方法可以让(内部)Bash 运行一些代码:

  1. bash可以从其标准输入读取代码:

    echo 'date; sleep 2; date' | bash
    

    标准输入可以是控制台。例如,您通常工作的交互bash从控制台读取,但它实际上从其标准输入读取,因为控制台它的标准输入。

  2. bash可以从文件中读取代码:

    bash /path/to/some/file
    

    (路径可能是相对的。)

  3. bash可以从命令行参数读取代码:

    bash -c 'date; sleep 2; date'
    

上下文

在评论中你说上下文是这个问题。我的回答建议更换:

wget -O - URL | bash

bash <(wget -O - URL)

第一个命令使内部bash从其标准输入读取。您似乎没有意识到第二个命令使内部bash读取不是其标准输入的文件。


会发生什么<(…)

当您bash <(wget -O - URL)在 Bash 中运行时,外部 Bash 会替换<(…)为某些路径文件。替换后,实际运行的命令可能如下所示:

bash /dev/fd/63

这会产生内部 Bash。它/dev/fd/63就像它会打开一样打开/path/to/some/file

由于进程替换的“魔力” /dev/fd/63,管道已经连接到wget -O - URL.

旁注:在/dev/fd不可用的系统上,外部 Bash 将使用真正命名的管道(例如/tmp/sh-np.pldKay)来进行设置。


相似度

在这两种情况下,从wget到(内部)的连接是相似的。bash当您运行时wget -O - URL | bashbash从其标准输入读取代码,该标准输入是管道wget写入的。当您运行时bash <(wget -O - URL),从管道写入的bash另一个文件(即不是从其标准输入)读取代码。wget在这两种情况下,外部 Bash 都会设置管道。


区别

不同之处在于,对于进程替换,内部 Bash 的标准输入不用于向其传递代码。标准输入可以用于其他目的。例如,标准输入可以是控制台,并且read在代码中可以从中读取。


对您明确问题的回答

  • 发明这个概念是为了解决什么问题

    当命令需要路径名(文件的路径)并且您想要通过管道输入某些内容而不是提供常规文件时,您可以创建命名管道并实现目标。这需要实际创建一个管道 ( mkfifo),向其传输某些内容(在后台或另一个控制台中),运行命令,最后删除命名管道 ( rm)。

    通过进程替换,Bash 可以处理管道。很方便。

  • 什么流程正在被取代?用什么取代?

    bash <(wget -O - URL)语法中<(wget -O - URL)替换为某个文件的路径,然后才执行命令(以及它bash /dev/fd/63或类似的命令)。外部 Bash 准备文件,因此从中读取意味着读取wget -O - URL(进程)写入的内容。该文件实际上是一个管道,而不是常规文件。

  • 它也被命名为“保留标准输入”吗?如果是的话为什么?

    “保留标准输入”发生,但它不是进程替换的替代名称。这不是一个正式的发生的事情的名称。

    当您bash …在(外部)Bash 中运行(内部)时,内部 Bash 会从外部 Bash 继承其标准输入(即,它是同一个文件)。标准输入可能是控制台。

    但如果你wget … | bash …改为运行,内部 Bash 将看到来自wget其自己的标准输入的数据。现在是内部 Bash 的某些部分(例如read 内置)或者内部 Bash 的某些子进程可能想从 stdin 读取一些内容。他们期望来自控制台或其他什么的输入,但是不是内部 Bash 应该执行的代码。但是因为内部 Bash 的标准输入是来自 的管道wget,内置程序将使用它,并且子进程将继承它作为他们的标准输入。它们不会继承外部 Bash 的标准输入。

    通过使用进程替换而不是通过 (内部) 的标准输入进行管道代码bash,您可以使外部 Bash 的标准输入可用于内部 Bash 的内置函数和子级。你保存外部 Bash 的标准输入,用于内部 Bash 的内置函数和子级。同时,您可以保护内部 Bash 读取和执行的代码流不被其内置函数或子函数读取。

    这只有效,因为bash允许您在指定为命令行参数的文件中提供代码。如果(内部)Bash 仅支持从 stdin 读取代码,那么您必须通过其 stdin 提供代码。在这种情况下,流程替代无法解决你遇到的问题

相关内容