Ruby komut dosyası içinde komut satırı komutlarını çalıştırma


92

Ruby aracılığıyla komut satırı komutlarını çalıştırmanın bir yolu var mı? 'Screen', 'rcsz' gibi komut satırı programlarını çevirip alıp gönderen küçük bir Ruby programı oluşturmaya çalışıyorum.

Tüm bunları Ruby (MySQL arka uç, vb.) İle ilişkilendirebilseydim harika olurdu.


Yanıtlar:


210

Evet. Birkaç yol var:


a. %xVeya '' ' kullanın :

%x(echo hi) #=> "hi\n"
%x(echo hi >&2) #=> "" (prints 'hi' to stderr)

`echo hi` #=> "hi\n"
`echo hi >&2` #=> "" (prints 'hi' to stderr)

Bu yöntemler stdout'u döndürür ve stderr'i programınkine yönlendirir.


b. Kullanım system:

system 'echo hi' #=> true (prints 'hi')
system 'echo hi >&2' #=> true (prints 'hi' to stderr)
system 'exit 1' #=> nil

trueKomut başarılı olursa bu yöntem geri döner . Tüm çıktıları programa yönlendirir.


c. Kullanım exec:

fork { exec 'sleep 60' } # you see a new process in top, "sleep", but no extra ruby process. 
exec 'echo hi' # prints 'hi'
# the code will never get here.

Bu, mevcut işlemi komut tarafından oluşturulanla değiştirir.


d. (yakut 1.9) kullanım spawn:

spawn 'sleep 1; echo one' #=> 430
spawn 'echo two' #=> 431
sleep 2
# This program will print "two\none".

Bu yöntem, işlemin çıkmasını beklemez ve PID'yi döndürür.


e. Kullanım IO.popen:

io = IO.popen 'cat', 'r+'
$stdout = io
puts 'hi'
$stdout = IO.new 0
p io.read(1)
io.close
# prints '"h"'.

Bu yöntem IO, yeni işlemlerin girdisini / çıktısını yeniden yorumlayan bir nesne döndürür . Ayrıca şu anda programa girdi vermenin bildiğim tek yolu bu.


f. Kullanım Open3(1.9.2 ve sonrasında)

require 'open3'

stdout,stderr,status = Open3.capture3(some_command)
STDERR.puts stderr
if status.successful?
  puts stdout
else
  STDERR.puts "OH NO!"
end

Open3iki çıktı akışına açık erişim elde etmek için birkaç başka işleve sahiptir. Popen'e benzer, ancak size stderr'e erişim sağlar.


Bonus numarası io = IO.popen 'cat > out.log', 'r+':; komutun çıktılarını "out.log" a yazar
Narfanator

1
Her birinin artıları ve eksileri nelerdir? Hangisini kullanacağıma nasıl karar veririm? FileUtils[ Ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html] kullanmaya ne dersiniz ?
Ava

1
Exec kullanarak bir SVN komutu yürütüyorum. Exec çıktısının konsolda görünmesini istemiyorum. Onu bir değişken olarak saklayabilmek ve bunun üzerinde bazı işlemler yapabilmek için yeniden yönlendirmek istiyorum. Nasıl yaparım ?
yığın1

2
durum başarılı mı? artık benim için ruby ​​2.4 üzerinde çalışmıyor, status.success olarak değiştirildi? :)
DanielG

14

Ruby'de sistem komutlarını çalıştırmanın birkaç yolu vardır.

irb(main):003:0> `date /t` # surround with backticks
=> "Thu 07/01/2010 \n"
irb(main):004:0> system("date /t") # system command (returns true/false)
Thu 07/01/2010
=> true
irb(main):005:0> %x{date /t} # %x{} wrapper
=> "Thu 07/01/2010 \n"

Ancak, komutun stdin / stdout ile gerçekten girdi ve çıktı gerçekleştirmeniz gerekiyorsa, muhtemelen IO::popenbu olanağı özellikle sunan yönteme bakmak isteyeceksiniz .


popen, uygulamanızın standardı varsa iyi çalışır. Daha fazla etkileşime ihtiyacınız varsa veya stdout, stdin ve özellikle stderr ile farklı bir şey yapmak istiyorsanız, open3: ruby-doc.org/core/classes/Open3.html
Paul Rubel

7
 folder = "/"
 list_all_files = "ls -al #{folder}"
 output = `#{list_all_files}`
 puts output

2

Evet, bu kesinlikle yapılabilir ancak uygulama yöntemi, söz konusu "komut satırı" programının "Tam ekran" veya komut satırı modunda çalışıp çalışmadığına bağlı olarak değişir. Komut satırı için yazılan programlar, STDIN okuma ve STDOUT'a yazma eğilimindedir. Bunlar, standart ters işaret yöntemleri ve / veya sistem / yürütme çağrıları kullanılarak doğrudan Ruby içinde çağrılabilir.

Program ekran veya vi gibi "Tam Ekran" modunda çalışıyorsa, bu durumda yaklaşımın farklı olması gerekir. Bunun gibi programlar için "beklenen" kitaplığının bir Ruby uygulamasını aramalısınız. Bu, ekranda görmeyi beklediğiniz şeyi ve bu belirli dizelerin ekranda göründüğünü gördüğünüzde ne göndermeniz gerektiğini yazmanıza olanak tanır.

Bunun en iyi yaklaşım olması pek olası değildir ve muhtemelen var olan bir tam ekran uygulamayı otomatikleştirmeye çalışmak yerine, elde etmeye çalıştığınız şeye bakmalı ve bunu yapmak için ilgili kitaplığı / cevheri bulmalısınız. Örnek olarak, " Ruby'de seri bağlantı noktası iletişimiyle ilgili yardıma ihtiyacınız var ", bahsettiğiniz belirli programları kullanarak elde etmek istediğiniz şey buysa çevirme için bir ön imleç olan Seri Bağlantı Noktası iletişimleriyle ilgilenir.


Ruby'de yerleşik Pty modülünü kullanan Expect'in basit bir sürümü mevcuttur .
The Tin Man

0

En Çok Kullanılan yöntem Open3Burada Kullanmaktır , yukarıdaki kodun bazı düzeltmelerle kodumun düzenlenmiş sürümüdür:

require 'open3'
puts"Enter the command for execution"
some_command=gets
stdout,stderr,status = Open3.capture3(some_command)
STDERR.puts stderr
if status.success?
  puts stdout
else
  STDERR.puts "ERRRR"
end
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.