Ruby kabuk komutlarını çağırma

oy
862

Nasıl bir Ruby programının içinden kabuk komutları denir? Nasıl O zamanlar Ruby içine Bu komutların çıktı alabilirim?

Oluştur 05/08/2008 saat 13:56
kaynak kullanıcı
Diğer dillerde...                            


20 cevaplar

oy
1k

Bu açıklama bir yorumladı dayanmaktadır Yakut komut benim bir arkadaşımdan. Komut dosyasını artırmak istiyorsanız, bağlantıyı güncellemek için çekinmeyin.

Birincisi, Ruby bir kabuk dışarı çağırdığında, genellikle çağırır unutmayın /bin/sh, değil Bash. Bazı Bash sözdizimi tarafından desteklenmeyen /bin/shtüm sistemlerde.

İşte bir kabuk yürütmek için yöntemler şunlardır:

cmd = "echo 'hi'" # Sample string that can be used
  1. Kernel#` Yaygın backticks denilen - `cmd`

    Bu Bash, PHP ve Perl gibi diğer birçok dilde gibidir.

    Kabuk komutunun sonucunu verir.

    Dokümanlar: http://ruby-doc.org/core/Kernel.html#method-i-60

    value = `echo 'hi'`
    value = `#{cmd}`
    
  2. Dahili sözdizimi, %x( cmd )

    Aşağıdaki xkarakteri herhangi bir karakter olabilir Bir sınırlayıcı vardır. Sınırlayıcı karakterlerden biri ise (, [, {, veya <, edebi yuvalanmış sınırlayıcı çiftleri dikkate alarak, eşleştirme kapanış sınırlayıcı kadar karakterden oluşur. Diğer tüm sınırlandırmalar için, hazır bilgi ayraç karakteriyle sonraki geçtiği kadar karakter içermektedir. Dize enterpolasyon #{ ... }izin verilir.

    Sadece ters tırnakların gibi, kabuk komutunun sonucunu verir.

    Dokümanlar: http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html

    value = %x( echo 'hi' )
    value = %x[ #{cmd} ]
    
  3. Kernel#system

    bir kabuktaki verilen komutu çalıştırır.

    İade truekomut, bulundu ve başarıyla çalıştırıldı eğer falseaksi.

    Dokümanlar: http://ruby-doc.org/core/Kernel.html#method-i-system

    wasGood = system( "echo 'hi'" )
    wasGood = system( cmd )
    
  4. Kernel#exec

    Verilen dış komutunu çalıştırarak geçerli sürecini değiştirir.

    Mevcut süreç yerini ve devam asla, hiç döndürür.

    Dokümanlar: http://ruby-doc.org/core/Kernel.html#method-i-exec

    exec( "echo 'hi'" )
    exec( cmd ) # Note: this will never be reached because of the line above
    

: İşte bazı ekstra bir tavsiye $?ile aynı olan $CHILD_STATUS, sen komutu ters tırnak kullanmak, eğer son sistem durumu komutu yürütür erişen system()veya %x{}. Daha sonra erişebilir exitstatusve pidözelliklerini:

$?.exitstatus

daha fazla okuma için bkz:

Cevap 05/08/2008 saat 15:42
kaynak kullanıcı

oy
150

Bunu yapmak ister yolu kullanıyor %xkolaylaştırır, hangi edebi şöyle bir komut tırnak kullanımı (ve okunabilir!):

directorylist = %x[find . -name '*test.rb' | sort]

Ki, bu durumda, beklendiği gibi işleyebilir geçerli dizinde altında tüm test dosyaları ile dosya listeyi oluşturacak:

directorylist.each do |filename|
  filename.chomp!
  # work with file
end
Cevap 05/08/2008 saat 15:08
kaynak kullanıcı

oy
140

İşte dayalı bir akış şeması var bu cevap . Aynı zamanda, bakınız kullanılarak scriptbir terminal taklit etmek için .

Burada görüntü açıklama girin

Cevap 19/05/2016 saat 17:01
kaynak kullanıcı

oy
58

İşte Ruby kabuk komut dosyalarını çalıştırma hakkında Bence en iyi makale: " 6 Yolları Ruby Shell Komutları çalıştırmak için ".

Yalnızca çıkış kullanımı komutu ters tırnak almak gerekiyorsa.

Ben STDOUT ve STDERR gibi daha gelişmiş şeyler yüzden Open4 mücevher kullanıldı gerekiyordu. Tüm yöntemler açıklanmıştır var.

Cevap 02/09/2008 saat 12:05
kaynak kullanıcı

oy
31

Benim favorim Open3

  require "open3"

  Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }
Cevap 18/09/2008 saat 18:47
kaynak kullanıcı

oy
23

Bu mekanizmaların arasında seçerken düşünmek bazı şeyler şunlardır:

  1. Sadece stdout'u istiyorum yoksa Stderr da gerekiyor yapıyorlar mı? ya da ayrılır?
  2. çıktı ne kadar büyük? Eğer bellekte tüm sonucu tutan istiyor musunuz?
  3. Eğer alt işlemi hala çalışırken sizin çıkış kısmını okumak istiyor musunuz?
  4. Eğer sonuç kodlarını ihtiyacınız var mı?
  5. İşlemi temsil eder ve talep üzerine onu öldürmek sağlayan bir yakut nesne gerekiyor mu?

Sen ( ``), sistem () ve basit ters tırnakların şey gerekebilir IO.popenşişmiş-dolu Kernel.fork/ Kernel.execile IO.pipeve IO.select.

bir alt işlemi yürütmek için çok uzun sürerse de karışımına zaman aşımları atmak isteyebilirsiniz.

Ne yazık ki, çok bağlıdır .

Cevap 07/08/2008 saat 06:10
kaynak kullanıcı

oy
19

Bir daha seçeneği:

Sen ne zaman:

  • stderr'yi yanı sıra stdout'u gerek
  • / Open3 / Open4 kullanmaz edemez (onlar benim Mac NetBeans istisnalar atmak, hiçbir fikri neden)

Kabuk yönlendirmeyi kullanabilirsiniz:

puts %x[cat bogus.txt].inspect
  => ""

puts %x[cat bogus.txt 2>&1].inspect
  => "cat: bogus.txt: No such file or directory\n"

2>&1Sözdizimi arasında çalışır Linux , Mac ve Windows'ta MS-DOS ilk günlerinden beri.

Cevap 16/06/2010 saat 03:13
kaynak kullanıcı

oy
15

Kesinlikle Yakut uzmanı değilim ama denemek gerekir:

$ irb 
system "echo Hi"
Hi
=> true

Ayrıca gibi şeyler yapmak mümkün olmalıdır:

cmd = 'ls'
system(cmd)
Cevap 05/08/2008 saat 14:24
kaynak kullanıcı

oy
11

Yukarıdaki cevaplar zaten oldukça büyük, ama gerçekten şu özet yazı paylaşmak istiyorum: " 6 Yolları Ruby Shell Komutları çalıştırmak için "

Temelde, söyler:

Kernel#exec:

exec 'echo "hello $HOSTNAME"'

systemve $?:

system 'false' 
puts $?

Ters tırnakların ( '):

today = `date`

IO#popen:

IO.popen("date") { |f| puts f.gets }

Open3#popen3 - stdlib:

require "open3"
stdin, stdout, stderr = Open3.popen3('dc') 

Open4#popen4 -- bir mücevher:

require "open4" 
pid, stdin, stdout, stderr = Open4::popen4 "false" # => [26327, #<IO:0x6dff24>, #<IO:0x6dfee8>, #<IO:0x6dfe84>]
Cevap 07/06/2013 saat 03:07
kaynak kullanıcı

oy
7

Eğer gerçekten "en iyi" yanıtında Not başına Bash gerekiyorsa.

Birincisi, Ruby bir kabuk dışarı çağırdığında, genellikle çağırır unutmayın /bin/sh, değil Bash. Bazı Bash sözdizimi tarafından desteklenmeyen /bin/shtüm sistemlerde.

Eğer Bash kullanmanız gerekirse, insert bash -c "your Bash-only command"istediğiniz çağıran yöntemin iç.

quick_output = system("ls -la")

quick_bash = system("bash -c 'ls -la'")

Test için:

system("echo $SHELL") system('bash -c "echo $SHELL"')

Veya varolan bir komut dosyası çalıştırıyorsanız (mesela script_output = system("./my_script.sh")) Ruby gerektiğini shebang onurlandırmak, ancak her zaman kullanabilirsiniz system("bash ./my_script.sh")hafif bir havai hususlar olmasına rağmen (emin olmak için /bin/shçalışan /bin/bash, muhtemelen fark etmez.

Cevap 02/06/2017 saat 20:14
kaynak kullanıcı

oy
7

Ayrıca Perl benzer backtick operatörleri ( `), kullanabilirsiniz:

directoryListing = `ls /`
puts directoryListing # prints the contents of the root directory

Kullanışlı basit bir şey gerekiyorsa.

Hangi sen başarmak için çalışıyoruz ne olduğuna bağlıdır kullanmak istediğiniz yöntemi; Farklı yöntemler hakkında daha fazla ayrıntı için dokümanlar kontrol edin.

Cevap 05/08/2008 saat 14:57
kaynak kullanıcı

oy
5

Unutma spawnbelirtilen komutu yürütmek için bir plan işlemi oluşturma komutu. Hatta kullanarak tamamlanmasını bekleyebilir Processsınıf ve iade pid:

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid

pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

Doktor diyor ki: Bu yöntem benzer #systemama bitirmek için komut için beklemez.

Cevap 04/11/2015 saat 15:04
kaynak kullanıcı

oy
5

Burada cevapları kullanma ve Mihai yanıtında bağlantılı, ben bu gereksinimleri karşılayan bir işlev araya:

  1. Düzgünce STDOUT ve STDERR yakalar böylece yaptıkları benim komut konsolundan çalıştırıldığında "sızıntı" değil.
  2. argümanları bir dizi olarak kabuk geçirilecek verir, böylece kaçan dert etmeye gerek yoktur.
  3. Bir hata oluştu zaman açıktır böylece komutun çıkış durumu yakalar.

Bir avantaj olarak, bu bir de kabuk komutu çıkışlar başarıyla (0) ve STDOUT şey koyar durumlarda STDOUT dönecektir. Bu şekilde, farklı systemsadece döndüren truebu gibi durumlarda.

Kod izler. Belirli fonksiyonudur system_quietly:

require 'open3'

class ShellError < StandardError; end

#actual function:
def system_quietly(*cmd)
  exit_status=nil
  err=nil
  out=nil
  Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thread|
    err = stderr.gets(nil)
    out = stdout.gets(nil)
    [stdin, stdout, stderr].each{|stream| stream.send('close')}
    exit_status = wait_thread.value
  end
  if exit_status.to_i > 0
    err = err.chomp if err
    raise ShellError, err
  elsif out
    return out.chomp
  else
    return true
  end
end

#calling it:
begin
  puts system_quietly('which', 'ruby')
rescue ShellError
  abort "Looks like you don't have the `ruby` command. Odd."
end

#output: => "/Users/me/.rvm/rubies/ruby-1.9.2-p136/bin/ruby"
Cevap 21/02/2012 saat 00:36
kaynak kullanıcı

oy
5

Biz çeşitli şekillerde bunu başarabilirsiniz.

Kullanımı Kernel#execBu komut sonrasında, hiçbir şey:

exec('ls ~')

kullanma backticks or %x

`ls ~`
=> "Applications\nDesktop\nDocuments"
%x(ls ~)
=> "Applications\nDesktop\nDocuments"

Kullanılması Kernel#system, komutu verir true, başarılı olursa falsebaşarısız olursa ve döner nilkomut yürütme başarısız olursa:

system('ls ~')
=> true
Cevap 19/02/2012 saat 19:07
kaynak kullanıcı

oy
4

En kolay yolu, örneğin geçerli:

reboot = `init 6`
puts reboot
Cevap 30/03/2017 saat 18:13
kaynak kullanıcı

oy
3
  • Ters tırnaklar `yöntem Ruby kabuk komutları aramak için en kolay olanıdır. Bu kabuk komutunun sonucunu verir.

     url_request = 'http://google.com'
     result_of_shell_command = `curl #{url_request}`
    
Cevap 16/02/2017 saat 09:58
kaynak kullanıcı

oy
3

Eğer ortak bir durumda daha karmaşık bir durum (yani ele alınamaz varsa ``) daha sonra kontrol Kernel.spawn() burada . Bu gibi görünüyor en genel / tam özellikli tarafından sağlanan stok Ruby dış komutları yürütmek için.

Örneğin bunu yapmak için kullanabilirsiniz:

  • süreç grupları oluşturmak (Windows)
  • / Dosyalara, dışarı, her-diğer hata içinde yönlendirir.
  • set env umask, vars
  • komutu yürütmeden önce dir değiştirmek
  • CPU / veri için ayarlanan kaynak limitleri / ...
  • ama daha kodla, diğer yanıtlar diğer seçenekleri ile yapılabilecek her şeyi yapın.

Resmi yakut belgeleri yeterince iyi örnekler vardır.

env: hash
  name => val : set the environment variable
  name => nil : unset the environment variable
command...:
  commandline                 : command line string which is passed to the standard shell
  cmdname, arg1, ...          : command name and one or more arguments (no shell)
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
  clearing environment variables:
    :unsetenv_others => true   : clear environment variables except specified by env
    :unsetenv_others => false  : dont clear (default)
  process group:
    :pgroup => true or 0 : make a new process group
    :pgroup => pgid      : join to specified process group
    :pgroup => nil       : dont change the process group (default)
  create new process group: Windows only
    :new_pgroup => true  : the new process is the root process of a new process group
    :new_pgroup => false : dont create a new process group (default)
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
    :rlimit_resourcename => limit
    :rlimit_resourcename => [cur_limit, max_limit]
  current directory:
    :chdir => str
  umask:
    :umask => int
  redirection:
    key:
      FD              : single file descriptor in child process
      [FD, FD, ...]   : multiple file descriptor in child process
    value:
      FD                        : redirect to the file descriptor in parent process
      string                    : redirect to file with open(string, "r" or "w")
      [string]                  : redirect to file with open(string, File::RDONLY)
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
      [:child, FD]              : redirect to the redirected file descriptor
      :close                    : close the file descriptor in child process
    FD is one of follows
      :in     : the file descriptor 0 which is the standard input
      :out    : the file descriptor 1 which is the standard output
      :err    : the file descriptor 2 which is the standard error
      integer : the file descriptor of specified the integer
      io      : the file descriptor specified as io.fileno
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
    :close_others => false : inherit fds (default for system and exec)
    :close_others => true  : dont inherit (default for spawn and IO.popen)
Cevap 11/12/2015 saat 14:57
kaynak kullanıcı

oy
1

Bir komutu Verilen örneğin attrib

require 'open3'

a="attrib"
Open3.popen3(a) do |stdin, stdout, stderr|
  puts stdout.read
end

Bu yöntem ters tırnakların örn sistemine ( "thecommand") veya thecommand gibi unutulmaz değilken, bu yöntem hakkında iyi bir şey diğer yöntemlerle karşılaştırıldığında olduğunu tespit ettik .. mesela backticks bana 'koyar izin vermiyor ise 'I / mağaza bir değişkende çalıştırmak istediğiniz komutu ve sistem ( 'thecommand') tarafından işletilen komut beni çıktısını alalım görünmüyor. Bu yöntem sağlar Oysa beni böyle şeyler her ikisini de ve bağımsız bana erişim Stdin, stdout ve stderr sağlar.

https://blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html

http://ruby-doc.org/stdlib-2.4.1/libdoc/open3/rdoc/Open3.html

Cevap 19/12/2017 saat 05:54
kaynak kullanıcı

oy
0

Gerçekten bir cevap ama belki birisi bu yararlı bulmak ve onun buna ilişkin olacaktır.

Windows üzerinde TK GUI kullanarak ve u rubyw gelen kabuk komutları çağırmak gerektiğinde, u her zaman rahatsız edici bir cmd penceresi Bir saniye sonra az haşhaş olacaktır.

Bunu önlemek için u kullanabilirsiniz

WIN32OLE.new('Shell.Application').ShellExecute('ipconfig > log.txt','','','open',0)

veya

WIN32OLE.new('WScript.Shell').Run('ipconfig > log.txt',0,0)

Hem 'log.txt' içeride ipconfig çıkışını saklar, ancak hiçbir pencere çıkacaktır.

U gerekecektir require 'win32ole'Senaryonuzun içeride.

system(), exec()Ve spawn()TK ve rubyw kullanırken tüm can sıkıcı pencerede o açılacaktır.

Cevap 05/07/2018 saat 12:55
kaynak kullanıcı

oy
-1

İşte (Ben senaryoyu başlatmak ve hatta penceresinden uzağa geçiş sonrasında bir güncelleme alabilmeleri) Ben OS X üzerinde bir yakut komut kullanmak serin bir tane:

cmd = %Q|osascript -e 'display notification "Server was reset" with title "Posted Update"'|
system ( cmd )
Cevap 14/10/2014 saat 21:12
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more