Ruby, exec, system ve% x () veya Backticks arasındaki fark


370

Aşağıdaki Ruby yöntemleri arasındaki fark nedir?

exec, systemVe %x()ya da ters tırnakların

Ruby aracılığıyla terminal komutlarını programlı olarak yürütmek için kullanıldıklarını biliyorum, ancak bunu yapmanın neden üç farklı yolu olduğunu bilmek istiyorum.


1
Bu komutlar ve diğerleri, dokümanlarda oldukça iyi açıklanmıştır: exec sistem backticks
zetetic

1
Bu konuda harika bir Ruby Quicktips makalesi var: Kabuk komutlarını yürütün .
Simon Perepelitsa

6
Birisi bu eski konuyu açtığından, "Unix Süreçleriyle Çalışma" konuyla ilgilenen Rubyistler için mükemmel bir kitaptır: workingwithunixprocesses.com
Michael Kohl

1
Cevapların hiçbirinin bahsetmediğine şaşırdım sh.
Dennis

@Dennis Bu soruyu gündeme getirdiğimde yakut 1.9.3 * yayınlanmadı.
Bay Black

Yanıtlar:


411

sistem

systemYöntem, bir sistem programı çağırır. Bu yönteme dize bağımsız değişkeni olarak komut sağlamanız gerekir. Örneğin:

>> system("date")
Wed Sep 4 22:03:44 CEST 2013
=> true

Çağrılan programı akımını kullanır STDIN, STDOUTve STDERRsenin Yakut programının itiraz ediyor. Aslında, gerçek dönüş değeri, bir true, falseya da nil. Örnekte tarih, öğesinin IO nesnesi aracılığıyla yazdırılmıştır STDIN. trueİşlem sıfır durumundan çıkmışsa, işlem sıfırdan farklı bir durumdan falseçıkmışsa ve nilyürütme başarısız olursa yöntem döndürülür .

Diğer bir yan etki ise global değişkenin $?bir Process::Statusnesneye ayarlanmış olmasıdır . Bu nesne, çağrılan işlemin süreç tanımlayıcısı (PID) ve çıkış durumu da dahil olmak üzere çağrının kendisi hakkında bilgi içerir.

>> system("date")
Wed Sep 4 22:11:02 CEST 2013
=> true
>> $?
=> #<Process::Status: pid 15470 exit 0>

backticks

Backticks (``) bir sistem programını çağırır ve çıktısını verir. İlk yaklaşımın aksine, komut bir dize ile değil, bir geri çene çifti içine yerleştirilerek sağlanır.

>> `date`
=> Wed Sep 4 22:22:51 CEST 2013   

Global değişken $?de ters çentiklerle ayarlanır. Backticks ile dize enterpolasyonunu da kullanabilirsiniz.

% X ()

Kullanmak %xbackticks tarzına bir alternatiftir. Çıktıyı da döndürür. Akrabaları %wve %q(diğerleri arasında) gibi, ayraç tarzı sınırlayıcılar eşleştiği sürece herhangi bir sınırlayıcı yeterli olacaktır. Bu araçlar %x(date), %x{date}ve %x-date-tüm eş anlamlıdır. Backticks %xgibi dize enterpolasyon kullanabilirsiniz.

exec

Kernel#execGeçerli işlemi kullanarak (Ruby betiğiniz) çağrılan işlemle değiştirilir exec. Yöntem, bir dizeyi bağımsız değişken olarak alabilir. Bu durumda dize kabuk genişletmesine tabi olacaktır. Birden fazla argüman kullanıldığında, ilk program bir programı yürütmek için kullanılır ve aşağıdakiler çağrılacak programa argümanlar olarak sağlanır.

Open3.popen3

Bazen gerekli bilgiler standart girdiye veya standart hataya yazılır ve bunlar üzerinde de kontrol sahibi olmanız gerekir. İşte Open3.popen3kullanışlı:

require 'open3'

Open3.popen3("curl http://example.com") do |stdin, stdout, stderr, thread|
   pid = thread.pid
   puts stdout.read.chomp
end

3
Ve çağrı kolları nasıl daha ince taneli kontrolü için STDIN, STDOUT, STDERR, düşünün Open3.popen3yerine; örneğin bkz. stackoverflow.com/a/10922097/258662
cboettig

1
Backticks sorunumu çözdü dize enterpolasyonu destek bahsettiğiniz için teşekkür ederim.
adg

244

İşte bu cevaba dayanan bir akış şeması . Ayrıca, bir terminali taklit etmek için kullanmascript konusuna bakın .

resim açıklamasını buraya girin


3
Bu o kadar basit değil. Benim durumumda "işlem tamamlanıncaya kadar engellemek için Tamam" ve sonra STDOUT / STDERR çıkışlarını kontrol etmek için popen3 kullanın.
Nakilon

Her zaman bir while döngüsüne sararak (etkin bir şekilde) engelleme çağrısının engellenmesine neden olabilirsiniz. Engellemeyen bir çağrıya engelleme çağrısı yapamazsınız.
Ian

106

Farklı şeyler yaparlar. execgeçerli işlemi yeni işlemle değiştirir ve hiçbir zaman geri dönmez . systembaşka bir işlemi çağırır ve çıkış değerini geçerli işleme döndürür . Backticks kullanmak başka bir işlemi çağırır ve bu işlemin çıktısını geçerli işleme döndürür .

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.