1

我正在尝试监视将 raspberry-pi OS 映像复制到 microSD 卡的进度。这类似于Kill a process called using open3 in ruby​​ ,除了我没有杀死该进程,我正在向它发送命令以发出进度消息。

  
    rpath = device_path.gsub(/disk/, "rdisk")
    puts "\n\nCopying image to #{rpath}"

    if false
      stdout_err, status = Open3.capture2e( "sudo", "dd", "bs=1m", "if=#{source_path}", "of=#{rpath}" )
      puts stdout_err
    else
      cmd = "sudo dd bs=1m if=#{source_path} of=#{rpath}"
      Open3.popen2e(cmd) do |stdin, stdout_err, wait_thr|
        Thread.new do
          stdout_err.each {|l| puts l}
        end

        Thread.new do
          while true
            sleep 5
            if true
              Process.kill("INFO", wait_thr.pid)      #Tried INFO, SIGINFO, USR1, SIGUSR1
                                                      # all give:  `kill': Operation not permitted (Errno::EPERM)
            else
              stdin.puts  20.chr      #Should send ^T -- has no effect, nothing to terminal during flash
            end
          end
        end

        wait_thr.value
      end

第一部分(在“if false”之后)使用Open3.capture2e闪烁图像。这可行,但当然不会发布任何进度信息。

'else' 之后的部分使用Open3.popen2e闪烁图像。它还尝试通过发出 'Process.kill("INFO", wait_thr.pid)' 或通过每 5 秒向标准输入流发送 ^T (20.chr) 来显示进度。

Process.kill行生成“不允许操作”错误。stdin.puts行完全没有效果。

另一件事......当 popen2e 进程闪烁时,在键盘上按 ctrl-T 确实会产生进度响应。我只是无法让它以编程方式完成。

任何帮助表示赞赏!

4

1 回答 1

0

较新的版本dd有一个可选的进度条,如此处所示。即便如此,我认为您仍需要重新考虑如何执行该 shell 命令,以便它认为它已连接到终端。最简单的事情是 fork/exec,例如:

cmd = "sudo dd bs=1m if=#{source_path} of=#{rpath} status=progress"
fork do
    exec(cmd) # this replaces the forked process with the cmd, giving it direct access to your terminal
end

Process.wait() # waits for the child process to exit

如果这不是一个选项,您可能想研究获得无缓冲输出的其他方法,包括仅编写 bash 脚本而不是 ruby​​ 脚本。

于 2020-10-09T16:04:19.207 回答