【问题标题】:Different results from same script同一脚本的不同结果
【发布时间】:2020-09-21 17:52:10
【问题描述】:

所以我有这个脚本

rm -f foo bar; cat foo > bar | cat bar > foo

我首先尝试在运行 Ubuntu 的机器上运行它。我原以为在cat foo 期间会出错,但它运行成功。然后我尝试在 AWS Cloud9 上运行它(也运行在相同版本的 Ubuntu 上),它给了我最初期望的错误。

之后,我尝试在不同的在线 bash 编译器上运行相同的命令,它们中的每一个都再次给了我不同的输出。第一个运行成功,第二个返回2个错误(foo不是文件,bar不是文件)。

为什么不同的机器从同一个脚本给出不同的输出?

【问题讨论】:

  • 此代码有竞争条件。它不仅在不同的机器之间会有所不同,而且在您在同一台机器上运行它的不同时间之间也会有所不同。
  • (请注意,它可能通常在一台机器上以一种方式运行,而通常在另一台机器上以不同方式运行,如果两者之间存在差异操作系统/负载配置文件/缓存设置等影响操作的时间;但两种行为都不比另一种更正确:您描述的两种结果对于按指定操作的 shell 解释器都是合法的。
  • @Amessihel,……没错。在 fork 的每一侧,输出文件的打开将在该侧的 cat 副本执行之前发生,但不能保证 fork 的一侧会领先于另一侧(或不会)。

标签: bash sh stdout io-redirection


【解决方案1】:

这是一种竞争条件,可能会产生多种结果,具体取决于安排的顺序和时间流程:

  1. 负责cat foo > bar 的shell 进程被调度,创建bar,执行cat,退出并出现关于foo 的错误
  2. cat bar > foo 类似地运行,创建 foo,读取 bar 为空。

  1. cat bar > foo 运行,创建 foo,退出时出现关于 bar 的错误
  2. cat foo > bar 运行,创建 bar,读取 foo 为空。

  1. cat foo > bar 运行,创建 bar,被抢占
  2. cat bar > foo 运行,创建 foo,被抢占
  3. cat foo 读取 foo 为空
  4. cat bar 读取 bar 为空

因此它可以在同一台机器上和不同的机器上给出不同的结果。

【讨论】:

  • 小心说“跑”。输出文件的创建发生在cat 的副本开始之前,如果我们想学究气的话;所以它不会暗示cat 在创建之前正在运行:)
  • 那么 |运营商究竟是做什么的?我认为cat bar > foo 部分应该运行当且仅当第一部分退出时出现错误。
  • @GuilhermeRaposo,你在想|| -- ref gnu.org/software/bash/manual/bash.html#Lists
  • @GuilhermeRaposo 我想您希望| 用作布尔“或”运算符 - 但那将是一个错误。该运算符是||,单个| 字符是“管道”。它使左侧命令的输出流作为输入流附加到其右侧的命令。然而,cat 命令既不产生有用的输出也不期望任何输入,因此管道只是同时运行这两个命令。
猜你喜欢
  • 2021-09-23
  • 2013-01-07
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-15
  • 2013-01-29
相关资源
最近更新 更多