1

ruby スクリプトを実行し、スクリプトでコマンドを実行している間にキーストロークに応答する方法はありますか?

Rubyスクリプトを実行したいのですが、「スペース」を押してスクリプトを一時停止し(現在実行中のコマンドが実行された後)、もう一度「スペース」を押してスクリプトを再開できるようにします。

私の唯一のアイデア(そしてそれは奇妙なものだと確信しています)は、新しいスレッドを開いてそこでキーストロークを待ち、キーストロークがうまくいかないときにstop_flagを設定することです。いつ停止するかを知るために、各コマンドの後にこのフラグをチェックする必要があるようです。

4

3 に答える 3

1

@Catnapper と同様のアイデアです。

require 'io/console' # Ruby 1.9

# Wait for the spacebar key to be pressed
def wait_for_spacebar
   sleep 1 while $stdin.getch != " "
end

# Fork a process that waits for the spacebar 
# to be pressed. When pressed, send a signal 
# to the main process.
def fork_new_waiter
   Process.fork do
      wait_for_spacebar
      Process.kill("USR1", Process.ppid)
   end
end

# Wait for a signal from the forked process
Signal.trap("USR1") do
   wait_for_spacebar

   # Debug code here

   fork_new_waiter
end

# Traps SIGINT so the program terminates nicely
Signal.trap("INT") do
   exit
end

fork_new_waiter

# Run program here in place of this loop
i = 0
loop do
   print i+=1
   sleep 1
end
于 2013-01-30T15:47:18.377 に答える
1

システムコマンドを使用できます。

Windows の場合: system "pause>null"

これは、OS ごとに異なります。そのため、変数を設定して OS をチェックできます。次に、適切なコマンドを使用します。OS が Windows かどうかを確認する場合、コードは次のようになります。

if RUBY_PLATFORM =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/ $operatingSystem="win" end

于 2014-01-10T20:09:51.030 に答える
1

スクリプト全体に適切なコードを散りばめたロガーを設定している場合は、信号を使用してデバッグ出力を自由にオンまたはオフにすることができます。

 pid = fork do

  # set up a logger
  require 'logger'
  log = Logger.new(STDOUT)
  log.level = Logger::INFO

  # toggle between INFO and DEBUG log levels on SIGUSR1
  trap(:SIGUSR1) do
    if log.level == Logger::DEBUG
      log.level = Logger::INFO
    else
      log.level = Logger::DEBUG
    end
  end

  # Main loop - increment a counter and occasionally print progress
  # as INFO level.  DEBUG level prints progress at every iteration.
  counter = 0
  loop do
    counter += 1
    exit if counter > 100
    log.debug "Counter is #{counter}"
    log.info "Counter is #{counter}" if counter % 10 == 0
    sleep 0.1
  end

end

# This makes sure that the signal sender process exits when the
# child process exits - only needed here to make the example
# terminate nicely.
trap(:SIGCLD) do
  exit(0) if Process.wait(-1, Process::WNOHANG) == pid
end

# This is an example of sending a signal to another process.
# Any process may signal another by pid.
# This example uses a forking parent-child model because this
# approach conveniently yields the child pid to the parent.
loop do
  puts "Press ENTER to send SIGUSR1 to child"
  STDIN.gets
  Process.kill :SIGUSR1, pid
end

分岐と SIGCLD トラップは、例を 1 つのファイルに収めるためのものです。どのプロセスも別のプロセスにシグナルを送ることができます。

fork ブロック内のコードはスクリプトです。このスクリプトは、デフォルトのログ レベルが INFO のロガーと、ロガーの DEBUG レベルと INFO レベルを切り替える SIGUSR1 シグナルのハンドラーをセットアップします。

fork ブロックの外側のものは、シグナルを別のプロセスに送信する例にすぎません。ENTER を押すと、シグナルが送信され、他のプロセスのログ レベルが変更されます。

これは POSIX システムで動作しますが、Windows についてはわかりません。

于 2013-01-30T15:14:31.940 に答える