Bash 非阻塞源(背景???)

Posted

技术标签:

【中文标题】Bash 非阻塞源(背景???)【英文标题】:Bash non blocking source (background???) 【发布时间】:2014-04-22 01:22:43 【问题描述】:

我试图让一个 bash 将参数传递给另一个 bash,我设法通过采购其中一个并从另一个调用它来做到这一点,这样它们就可以成为同一个 shell 下的父子。问题是孩子是一个循环,因为我正在托盘捕获事件(它可能正在读取一个fifo(管道文件))并且这阻止了bash......对,所以我觉得嗯,让我们尝试在后台运行bash并且我在这里遇到的问题是我猜这些变量不是 int 因为我猜它不在同一个外壳下我尝试采购和支持但没有积极的结果......

在某些时候,当我发送到 fifo(管道文件)时,我的 shell 开始变得疯狂,即使没有(我知道正在读取)它的行为就好像有什么东西已经读取了该 fifo,以及我的其他一些 bash 屏幕开始做疯狂的事情......:O

无论如何,我想知道是否有人可以帮助我。不知道我想要做的事情是否可能......谢谢。

不知道我在哪里读到(还不能再次找到该页面)将脚本移动到后台使其可以访问父子进程、子进程及其爸爸妈妈,但这不是我现在的经验。

bash1

   #!/bin/bash

    while true
    do

    . ./bash2.sh &

    if [[ $VARIABLE = 1 ]]; then
    echo "message recevied"
    fi

bash2

  #!/bin/bash

    while true
    do

    if [[ $(cat ./fifo1) = 0 ]]; then
    VARIABLE=1
    fi
    done

谢谢

【问题讨论】:

bash2 假设将 VARIABLE 设置为 1 并且 bash1 将从 bash2 中读取,对吗? 【参考方案1】:

因为&总是启动一个新进程,所以两者差别不大

. ./bash2.sh &

# Assuming bash2.sh is executable
./bash2.sh &

bash2.sh 定义的任何变量都仅限于执行它的进程; bash1.sh 无法使用它们。你的选择是

    在前台运行. ./bash2.sh,并等待它完成 让./bash2.sh 写入bash1.sh 的东西(文件、命名管道等) 可以读取。

【讨论】:

我认为我不得不选择 #2 altought 我不得不说这不是一个令人信服的选择,因为如果使用管道我仍然有阻塞问题,它会留在那里等待一些东西进来,并且如果它没有我可能会丢失数据,我可以在中间创建一个函数来存储更改并放置一个标志,但是我会再次像 bash2 一样做同样的事情......有人知道关于 Unix 域套接字的任何事情吗?这会让我工作让脚本运行,另一个也在运行,并且一个变量上的任何变量都在另一个上? - 谢谢 无论如何你都会遇到阻塞问题,但是内置的read 支持指定超时的-t 选项,因此您可以在重试之前做一些其他工作。跨度> 【参考方案2】:

好吧,您已经很接近了,但是您在提供的示例中存在一些错误。首先,您不需要在任一脚本中使用 While 循环,因为它在您提供的代码示例中没有任何用途,因此我在示例中省略了它们。

示例 1

#!/bin/bash

external_function()
   echo "This is printed from the sourced script"; 
   [ -e ./fifo1 ] && return $TRUE || return $FALSE

示例 2

#!/bin/bash

source ./test.sh
external_function && echo "the file exists" || echo "The file doesn't exist" 
exit

您正在做的是使用. (source or dot operator),它将在当前 shell 上下文中从文件名参数读取并执行命令。

语法

  . filename [arguments]

  source filename [arguments]

当使用源代码运行脚本时,它在现有 shell 中运行,脚本创建或修改的任何变量在脚本完成后仍然可用。相反,如果脚本仅作为文件名运行,则将生成一个单独的子 shell(具有一组完全独立的变量)来运行脚本。

这意味着您确实想要使用& 将第二个脚本派生到一个新进程,因为它永远不会返回到主脚本。

此外,我通常会将我希望在第二个(源代码)脚本中运行的代码放在一个函数中。我认为它更易于阅读,您可以使用它来检查函数的返回码,从而使调试更加容易。

最后,if [[ $(cat ./fifo1) = 0 ]] 只是在检查 cat 命令的退出状态时是否存在。您可以简单地使用以下行:

[ -e / ] && return $TRUE || return $FALSE

-e 是一个 bash File Test Operator,用于检查 FILE 是否存在。

&& 是一个 bash Operator,如果最后一个命令返回成功退出代码(非零),它将运行以下命令

|| 是一个 bash Operator,如果最后一个命令返回失败的退出代码(零),它将运行以下命令

进一步阅读

我在 bash 中经常使用这个 reference,我认为值得一提

【讨论】:

嗨,马特,感谢您提供如此详细的答案。正如我在文本中所说,我尝试过采购,问题在于这会阻塞代码,并且由于孩子有一个循环,它会永远留在那里。另一方面,fifo 一直存在,所以不知道这是否可行。虽然生病了试一试。再次感谢。

以上是关于Bash 非阻塞源(背景???)的主要内容,如果未能解决你的问题,请参考以下文章

在linux / bash中使用非阻塞FIFO流式传输视频

Golang 阻塞和非阻塞

linux5种IO模型以及同步异步,阻塞非阻塞

阻塞IO非阻塞IOIO多路复用同步IO异步IO 的理论

进程之并行并发同步异步与阻塞非阻塞

五种Linux IO模型+同步异步,阻塞非阻塞,再也不怕头条面试官挂我了