ruby - 在 bash 中打开一个命名管道,而不读取或写入它

标签 ruby linux bash shell named-pipes

我想在 bash 中使用命名管道而不读取或写入它,直到事件发生。我需要在 shell 脚本运行的整个过程中保持此管道打开。我会在需要时阅读它。意思是,可以这样做吗:

open(<$NAMED_PIPE>, "r+")
--do something--
--call child ruby script, which will write to named pipe--
--do something more---
read line < $NAMED_PIPE

这在 bash 中可行吗?

我正在使用以下代码: ../ ruby |-- try1.rb `-- try2.sh

try1.rb如下:

#!/usr/bin/ruby

require 'optparse'

puts 'Hello World!, This is my first ruby program'

options = {}

optparse = OptionParser.new do|opts|

  opts.banner = "Featbuild minimal trial script for command line parsing"

  options[:cpl] = nil
  opts.on('--cpl SWITCH_STATE', 'compile on or off') do|cplopt|
      options[:cpl] = cplopt
      OPT_CPL=cplopt
      puts cplopt
  end

  opts.on('-h', '--help', 'Display this screen') do
    puts opts
    exit
  end
end

optparse.parse!

output = open("mypipe", "w+")

output.puts OPT_CPL
output.flush

还有 try2.sh 脚本(调用 ruby​​ 脚本):

#!/bin/sh



mkfifo mypipe
exec 4< /home/yusufh/Ruby/mypipe

OPT=$*
./try1.rb ${OPT}


#read -ru 4 line
read line <&4

echo $line


exec 4<&- #close FIFO my_pipe

rm mypipe

@konsolebox,当我使用一个普通的文本文件从 ruby​​ 脚本复制数据时,您的解决方案有效,bash 脚本本身从那里获取它。 但是,在尝试使用命名管道时,bash 脚本会在执行以下语句后阻塞:exec 4< /home/yusufh/Ruby/mypipe .控制不会产生 ruby​​ 脚本进程,数据将在其中生成,之后 bash 脚本的实际等待/阻塞必须在这一行完成:read line <&4 . 因此,我想要实现的目标没有发生。此外,当 bash 在获取 FIFO 的 fd 时等待时,如果我将某些内容回显到重复终端上的命名管道中,它就会退出等待并继续进行。但是在这种情况下,从 Ruby 脚本返回的数据也没有写入 FIFO,正如我观察到的那样。这是 Debug模式下 scritps 的输出:

[yusufh@verigybuild6 Ruby]$ bash -xv try2.sh --cpl on &
[1] 2777
[yusufh@verigybuild6 Ruby]$ #!/bin/sh



mkfifo mypipe
+ mkfifo mypipe
exec 4< /home/yusufh/Ruby/mypipe
+ exec

[yusufh@verigybuild6 Ruby]$ echo "Hello World" > mypipe
[yusufh@verigybuild6 Ruby]$
OPT=$*
+ OPT='--cpl on'
./try1.rb ${OPT}
+ ./try1.rb --cpl on
Hello World!, This is my first ruby program
on


#read -ru 4 line
read line <&4
+ read line

echo $line
+ echo Hello World
Hello World


exec 4<&- #close FIFO my_pipe
+ exec

rm mypipe
+ rm mypipe



[1]+  Done                    bash -xv try2.sh --cpl on
[yusufh@verigybuild6 Ruby]$

关于失败原因的任何想法?感谢您的努力! :-)

最佳答案

使用 Bash 非常简单:

# Open the named pipe with a custom fd for input
exec 4< /path/to/named_pipe

# Do other things
:

# Read a line from pipe
read -ru 4 line

# Or
read -r line <&4

# Just make this consistent and close it when you're done. May not be necessary at exit but still a good practice.
exec 4<&-
  • 当使用 read 读取输入时,最好使用 -r 来防止反斜杠转义任何字符
  • 在未设置 IFS 的情况下运行 read (IFS= read ...) 也可能有助于防止修剪前导和尾随空格。

类似的概念也适用于写作:

exec 4> /path/to/named_pipe
echo something >&4
exec 4>&-

奖励:您还可以在 block 范围内打开命名管道,例如 {}whilefor if, until 等。有了它就没有必要关闭文件描述符了:

{
    # Do reads and other things
    ...
} 4< /path/to/named_pipe

关于ruby - 在 bash 中打开一个命名管道,而不读取或写入它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24730550/

相关文章:

ruby-on-rails - Rails ActiveRecord - 查询关系的最后记录

ruby - 在 Sinatra 中缓存响应的最佳方式?

mysql - "Can' t 使用自定义外键时将未知属性写入HABTM连接表

php - linux mint 中禁止访问 apache localhost

bash -/bin/bash -c 与直接执行命令有何不同?

linux - 如何让 GNU screen 读取 .bash_profile/.bash_rc 更改?

ruby-on-rails - 如何在 ruby​​ on rails 中添加和合并来自不同哈希数组的值

linux - 我如何 grep 出相同模式的多行?

c - 关于内存管理中函数arch_get_unmapped_area的一个问题(linux)

python - ssh-agent ssh-add ok in user not in sudo