标签: popen3

如何从ruby Open3.popen3()中检索退出状态?

我似乎被困在尝试检索从ruby的Open3.popen3()方法启动的shell命令的退出状态.

这是我的代码:

require 'open3'
stdin, stdout, stderr = Open3.popen3('ls')
Run Code Online (Sandbox Code Playgroud)

当我现在尝试访问$?它仍然是nil

毕竟可以检索退出状态吗?

注意:
- ls不是我试图在我的脚本中使用的命令.我只是用它来举个例子.我的脚本有点复杂并且包含用户输入,这就是我需要Open3的清理功能的原因.
- 我也尝试了popen3的块变体,但也没有成功.

ruby popen3

19
推荐指数
2
解决办法
9750
查看次数

如何在Ruby中修复挂起的popen3?

我使用popen3得到了意想不到的行为,我想用它来运行像工具ala这样的命令cmd < file1 > file2.以下示例挂起,因此stdout done永远不会到达.使用其他cat可能导致悬挂的工具,从而stdin done永远不会达到.我怀疑,我正在缓冲,但我该如何解决这个问题呢?

#!/usr/bin/env ruby

require 'open3'

Open3.popen3("cat") do |stdin, stdout, stderr, wait_thr|
  stdin.puts "foobar"

  puts "stdin done"

  stdout.each_line { |line| puts line }

  puts "stdout done"

  puts wait_thr.value
end

puts "all done"
Run Code Online (Sandbox Code Playgroud)

ruby popen3

14
推荐指数
3
解决办法
7654
查看次数

ruby popen3 - 如何重复写入stdin并读取stdout而无需重新打开过程?

我正在使用Open3popen3方法来启动一个以类似控制台/ REPL方式运行的进程,以反复接受输入和返回输出.

我可以打开进程,发送输入,并接收输出就好了,代码如下:

Open3.popen3("console_REPL_process") do |stdin, stdout, stderr, wait_thr|
    stdin.puts "a string of input"
    stdin.close_write
    stdout.each_line { |line| puts line } #successfully prints all the output
end
Run Code Online (Sandbox Code Playgroud)

我想连续多次这样做,而不需要重新打开过程,因为启动需要很长时间.

我知道我必须关闭stdin以便stdout返回..但我不知道的是,我如何重新打开'stdin以便我可以写更多输入?

理想情况下,我想做这样的事情:

Open3.popen3("console_REPL_process") do |stdin, stdout, stderr, wait_thr|
    stdin.puts "a string of input"
    stdin.close_write
    stdout.each_line { |line| puts line }

    stdin.reopen_somehow()

    stdin.puts "another string of input"
    stdin.close_write
    stdout.each_line { |line| puts line }
    # etc..
end
Run Code Online (Sandbox Code Playgroud)

感谢pmoo的回答,我能够使用PTY和设计一个解决方案,并expect期望当进程准备好输入时进程返回的提示字符串,如下所示:

PTY.spawn("console_REPL_process") do |output, input| …
Run Code Online (Sandbox Code Playgroud)

ruby popen3

9
推荐指数
1
解决办法
2562
查看次数

使用带超时的多线程时,ruby Open3.capture3 中的关闭流(IOError)

我希望运行几个系统命令,并得到以下信息:

  1. 我希望在同一进程下的不同线程中运行每个命令
  2. 我希望捕获并存储输出和退出状态。
  3. 我希望在执行时间上设置超时以查找某些系统命令是否被卡住。

不幸的是下面的代码最终是:

/usr/lib/ruby/1.9.1/open3.rb:276:in read': closed stream (IOError) from /usr/lib/ruby/1.9.1/open3.rb:276:incapture3' 中的块(2 级)

有时,取决于线程调度。例如,当将超时更改为 2 秒(或完全删除超时块)时,代码可以正常工作。

这是示例代码:

require 'open3'
require 'timeout'

def output_from(command)
  o, e, s = Open3.capture3(command)
  return o
end

attempts = 0
Thread.abort_on_exception = true
for i in 0..5
  Thread.new {
    begin
      Timeout::timeout(0.0001) {
        output = output_from('cat /proc/cpuinfo')
      }
    rescue Timeout::Error => e
      attempts+=1
      retry unless attempts > 2
    end
  }
end

puts attempts
Run Code Online (Sandbox Code Playgroud)

我曾尝试rescueinoutput_from方法并关闭 o,但它也没有帮助。我感觉线程以某种方式共享 popen3 实现中的管道或一些变量。

ruby timeout popen popen3

6
推荐指数
0
解决办法
1020
查看次数

Ruby-Open3.popen3 /如何打印输出

我有一个小的ruby脚本,它在mysql导入方式:mysql -u <user> -p<pass> -h <host> <db> < file.sql但是利用Open3.popen3这样做.这就是我到目前为止:

mysqlimp = "mysql -u #{mysqllocal['user']} "
mysqlimp << "-h #{mysqllocal['host']} "
mysqlimp << "-p#{mysqllocal['pass']} "
mysqlimp << "#{mysqllocal['db']}"

Open3.popen3(mysqlimp) do |stdin, stdout, stderr, wthr|
  stdin.write "DROP DATABASE IF EXISTS #{mysqllocal['db']};\n"
  stdin.write "CREATE DATABASE #{mysqllocal['db']};\n"
  stdin.write "USE #{mysqllocal['db']};\n"

  stdin.write mysqldump #a string containing the database data
  stdin.close

  stdout.each_line { |line| puts line }
  stdout.close

  stderr.each_line { |line| puts line }
  stderr.close
end
Run Code Online (Sandbox Code Playgroud)

这实际上是在做这项工作,但是有一件事困扰着我,关心我希望看到的输出.

如果我将第一行更改为:

mysqlimp = …
Run Code Online (Sandbox Code Playgroud)

ruby popen3

6
推荐指数
1
解决办法
6076
查看次数

杀死在ruby中使用open3调用的进程

我正在使用命令行程序,它的工作原理如下:

$ ROUTE_TO_FOLDER/app < "long text"
Run Code Online (Sandbox Code Playgroud)

如果使用参数"app"需要写入"长文本",那么它将填充带有结果的文本文件.如果没有,它将连续用点填充文本文件(我无法处理或修改"app"的代码以避免这种情况).

在ruby脚本中有一行如下:

text = "long text that will be used by app"
output = system("ROUTE_TO_FOLDER/app < #{text}")
Run Code Online (Sandbox Code Playgroud)

现在,如果文本写得很好,就不会有问题,我会得到一个如前所述的输出文件.文本写得不好时会出现问题.接下来发生的是我的ruby脚本挂起,我不知道如何杀死它.

我找到了Open3,我使用了这样的方法:

irb> cmd = "ROUTE_TO_FOLDER/app < #{text}"
irb> stdin, stdout, stderr, wait_thr = Open3.popen3(cmd)
=> [#<IO:fd 10>, #<IO:fd 11>, #<IO:fd 13>, #<Thread:0x007f3a1a6f8820 run>]
Run Code Online (Sandbox Code Playgroud)

当我做:

irb> wait_thr.value
Run Code Online (Sandbox Code Playgroud)

它也挂起,并且:

irb> wait_thr.status
=> "sleep"
Run Code Online (Sandbox Code Playgroud)

所以...¿我怎样才能避免这些问题?¿是不是认识到"app"失败了?

提前致谢

ruby popen3

6
推荐指数
1
解决办法
3379
查看次数

使用python执行shell邮件命令

我使用以下代码按照类似主题的帖子中的建议发送电子邮件.但邮件尚未发送.有什么建议?

import subprocess
recipient = 'xxxxx@gmail.com'
subject = 'test'
body = 'testing mail through python'
def send_message(recipient, subject, body):
    process = subprocess.Popen(['mail', '-s', subject, recipient],
                               stdin=subprocess.PIPE)
    process.communicate(body)

print("sent the email")
Run Code Online (Sandbox Code Playgroud)

python email subprocess process popen3

6
推荐指数
1
解决办法
5629
查看次数

Runy Open3.popen3从命令行在子过程中输入输入

目标:我正在用ruby编写一个工作流命令行程序,该程序在UNIX shell上顺序执行其他程序,其中一些程序需要用户输入输入。

问题:虽然我可以成功地处理stdout,并stderr感谢这个有用的博客文章尼克·查尔顿,不过,我卡在捕捉用户输入,并将其传递到子过程通过命令行。代码如下:

方法

module CMD
  def run(cmd, &block)
    Open3.popen3(cmd) do |stdin, stdout, stderr, thread|
      Thread.new do # STDOUT
        until (line = stdout.gets).nil? do
          yield nil, line, nil, thread if block_given?
        end
      end

      Thread.new do # STDERR 
        until (line = stderr.gets).nil? do
          yield nil, nil, line, thread if block_given?
        end
      end

      Thread.new do # STDIN
        # ????? How to handle
      end

      thread.join
    end
  end
end 
Run Code Online (Sandbox Code Playgroud)

调用方法

此示例调用shell命令units,该命令提示用户输入度量单位,然后提示您将其转换为单位。这就是它在外壳中的外观

> …
Run Code Online (Sandbox Code Playgroud)

ruby shell command-line stdin popen3

5
推荐指数
1
解决办法
923
查看次数

ruby open3 stdout 和 stdin 如何交互

sum.rb很简单。您输入两个数字,它返回总和。

# sum.rb
puts "Enter number A"
a = gets.chomp
puts "Enter number B"
b = gets.chomp
puts "sum is #{a.to_i + b.to_i}"
Run Code Online (Sandbox Code Playgroud)

robot.rb用于Open3.popen3sum.rb. 这是代码:

# robot.rb
require 'open3'

Open3.popen3('ruby sum.rb') do |stdin, stdout, stderr, wait_thr| 
  while line = stdout.gets
    if line == "Enter number A\n"
      stdin.write("10\n")
    elsif line == "Enter number B\n"
      stdin.write("30\n")
    else
      puts line
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

robot.rb无法运行。似乎它停留在sum.rb's gets.chomp

后来我发现我必须写如下才能使它工作。您需要事先以正确的顺序为它提供输入。

# robot_2.rb
require 'open3'

Open3.popen3('ruby sum.rb') do …
Run Code Online (Sandbox Code Playgroud)

ruby popen3

5
推荐指数
1
解决办法
978
查看次数

脚本化openssl可以生成许多证书,而无需手动输入密码?

我已经创建了证书颁发机构,并且需要生成并签署50多个证书。我想编写这个过程的脚本。我不想手动输入密码100次以上!

这是我挂断的命令:

openssl req -newkey rsa:1024 -keyout ~/myCA/tempkey.pem -keyform PEM -out ~/myCA/tempreq.pem -outform PEM
Run Code Online (Sandbox Code Playgroud)

问题是,它要我用以下提示创建密码:

Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Run Code Online (Sandbox Code Playgroud)

当系统仅要求我输入密码时,可以使用的-passin pass:mypass命令行选项openssl。但这似乎不适用于创建密码。

另外,当以后我最终将其删除时,需要输入密码似乎很奇怪:

openssl rsa < tempkey.pem > server_key.pem
Run Code Online (Sandbox Code Playgroud)

我尝试创建一个简单的Ruby脚本:

require 'open3'

Open3.popen2("openssl req -newkey rsa:1024 -keyout ~/myCA/tempkey.pem -keyform PEM -out ~/myCA/tempreq.pem -outform PEM") {|i,o,t|
    i.puts "mySecretPassword"
    i.puts "mySecretPassword"
}
Run Code Online (Sandbox Code Playgroud)

但这似乎也不起作用。我仍然遇到一个手动提示,要求我创建密码。

ruby command-line openssl input popen3

4
推荐指数
2
解决办法
2129
查看次数

为什么Open3.popen3在缺少可执行文件时返回错误的错误?

我正在围绕CLI创建一个Ruby包装器.我发现了一个简洁的方法Open3.capture3(内部使用Open3.popen3),它允许我执行命令并捕获stdout,stderr和退出代码.

我想要检测的一件事是,是否找不到CLI可执行文件(并为此引发特殊错误).我知道UNIX shell 127在找不到命令时会提供退出代码.当我$ foo在bash中执行时,我得到了-bash: foo: command not found,这正是我想要显示的错误消息.

考虑到所有这些,我编写了这样的代码:

require "open3"

stdout, stderr, status = Open3.capture3(command)
case status.exitstatus
when 0
  return stdout
when 1, 127
  raise MyError, stderr
end
Run Code Online (Sandbox Code Playgroud)

但是,当我运行它时command = "foo",我收到一个错误:

Errno::ENOENT: No such file or directory - foo
  /Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:193:in `spawn'
  /Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:193:in `popen_run'
  /Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:93:in `popen3'
  /Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:252:in `capture3'
Run Code Online (Sandbox Code Playgroud)

为什么会出现此错误?我以为Open3.capture3应该直接在shell中执行该命令,为什么我不能得到正常的STDERR并退出代码127

ruby popen3

3
推荐指数
1
解决办法
2588
查看次数

Perl:让open3继承STDIN,STDOUT,STDERR

这个打印1..10两次:

seq 10 > /tmp/ten
perl -e 'fork();seek(STDIN,0,0); print <STDIN>' </tmp/ten
Run Code Online (Sandbox Code Playgroud)

我想使用IPC :: Open3做同样的事情,但我不能让它工作:

perl -MIPC::Open3 -e 'fork();seek(STDIN,0,0); open3(0,1,2,"cat");' < /tmp/ten
perl -MIPC::Open3 -e 'fork();seek(STDIN,0,0); open3(STDIN,STDOUT,STDERR,"cat");' < /tmp/ten
perl -MIPC::Open3 -e 'fork();seek(STDIN,0,0); open3(*STDIN,*STDOUT,*STDERR,"cat");' < /tmp/ten
perl -MIPC::Open3 -e 'fork();seek(STDIN,0,0); open3(\*STDIN,\*STDOUT,\*STDERR,"cat");' < /tmp/ten
Run Code Online (Sandbox Code Playgroud)

perl popen3

3
推荐指数
1
解决办法
266
查看次数

在 lua io.popen 中使用 stderr 来确定错误的函数调用

我正在制作一个函数,可以读取 Spotify 中当前播放的歌曲的元数据。这是用 lua 编程的,因为它是很棒的 wm 的实现。我得到了以下行来获取我以后可以使用的所有元数据。

handle = io.popen('qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Metadata | awk -F: \'{$1=\"\";$2=\"\";print substr($0,4)}\'') 
Run Code Online (Sandbox Code Playgroud)

但是,当 Spotify 未运行时,我无法获得预期的信息,并且 qdbus 会向 stderr 流写入错误。我想利用 qdbus 写入错误流的事实来确定故障并在那里停止程序。(这还应该捕获与 Spotify 是否正在运行无关的任何其他错误)

我的理解是lua popen使用popen3可以在stdout和stderr之间细分。但到目前为止我的所有努力都是徒劳的,我的错误流总是空的。是否可以检查 stderr 中的非 nil 值以确定对 qdbus (或 awk)的错误调用?

谢谢!

lua stderr awesome-wm qdbus popen3

2
推荐指数
1
解决办法
3692
查看次数

标签 统计

popen3 ×13

ruby ×10

command-line ×2

awesome-wm ×1

email ×1

input ×1

lua ×1

openssl ×1

perl ×1

popen ×1

process ×1

python ×1

qdbus ×1

shell ×1

stderr ×1

stdin ×1

subprocess ×1

timeout ×1