Ruby'den qabıq əmrləri çağırırıq

Ruby proqramından qabıq əmrləri necə çağırırsınız? Ruby'ye bu əmrlərdən necə çıxa bilərəm?

941
05 авг. CodingWithout tərəfindən hazırlanıb 05 Avqust. 2008-08-05 15:56 '08 at 15:56 2008-08-05 15:56
@ 20 cavab

Bu şərh mənim yoldaşımın " Ruby " şərhinə əsaslanır. Skripti inkişaf etdirmək istəyirsinizsə, onu istinad edərək yeniləyin.

Birincisi, Ruby kabuğu çağırdığında adətən, /bin/sh deyil, Bash deyil. Bəzi Bash sintaksisləri bütün sistemlərdə /bin/sh tərəfindən dəstəklənmir.

Bir kabuk skriptini çalıştırma yolları bunlardır:

 cmd = "echo 'hi'" # Sample string that can be used 
  1. Kernel#' , yaygın olaraq arka arkaya çağrılan - 'cmd'

    Bu, bash, php və perl daxil olmaqla bir çox digər dillərə bənzəyir.

    Shell əmrinin nəticəsini qaytarır.

    Sənədlər: http://ruby-doc.org/core/Kernel.html#method-i-60

     value = 'echo 'hi'' value = '#{cmd}' 
  2. Daxili sintaksis, %x( cmd )

    x xarakterdən sonra hər hansı bir xarakter ola bilən bir ayırıcıdır. Sınırlayıcı karakterlerden biri ise ( , [ , { və ya < , literal, ayrıştırılmış cüt sınırlayıcıları kapsayan, müvafiq kapama sınırlayıcıya kadar olan simgelerden oluşur.) Bütün diğer sınırlayıcılar üçün, harfi, sınırlayıcı karakterin bir sonrakı yarısına kadar karakterleri ehtiva edir #{... } .

    Shell əmrinin nəticəsini və tərs siqnallarını qaytarır.

    Sənədlər: http://www.ruby-doc.org/docs/ProgrammingRuby/html/>

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

    Bu əmri bir subshelldə yerinə yetirir.

    Komanda tapıldı və uğurla yerinə yetirildiyi təqdirdə true olur, əksinə false .

    Sənədlər: http://ruby-doc.org/core/Kernel.html#method-i-system

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

    Bu xarici komandanı icra etməklə mövcud prosesi dəyişdirir.

    Heç bir şey qaytarmaz, mövcud proses dəyişir və heç vaxt davam edir.

    Sənədlər: 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 

Bəzi əlavə məsləhətlər: $? $CHILD_STATUS ilə eyni olan, backtracks, system() və ya %x{} istifadə etdiyiniz sistem tərəfindən icra edilən son əmr statusuna daxil olur. Sonra exitstatuspid xüsusiyyətlərinə daxil ola bilərsiniz:

 $?.exitstatus 

Daha ətraflı məlumat üçün bax:

1210
05 авг. Steve Willard tərəfindən verilmiş cavab 05 Av 2008-08-05 17:42 '08 at 5:42 pm 2008-08-05 17:42

Ruby'teki kabuk skriptlerini yayınlama konusunda düşündüğüm en yaxşı makale: " Ruby'də konsol əmrlərini çalıştırmanın 6 yolu .

Yalnız çıxışı almaq istəyirsinizsə, geri istifadə edin.

STDOUT və STDERR kimi daha inkişaf etmiş şeylərə ehtiyac duyduğum üçün Open4 daşını istifadə etdim. Bütün üsullar var.

59
02 сент. Cavab Mihai A 02 Sentyabr tərəfindən verilir. 2008-09-02 14:05 '08 saat 02:05 'da 2008-09-02 14:05

Xoşladığım Open3

  require "open3" Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... } 
32
18 сент. Anshul tərəfindən verilmiş cavab 18 sentyabr 2008-09-18 20:47 '08 at 8:47 pm 2008-09-18 20:47

Bu mexanizmlər arasında seçim zamanı nəzərə alınacaq bəzi məsələlər:

  • Yalnız stdout istəyirik və ya stderr lazımdır? hətta ayrılmış?
  • Məhsulunuz necə böyükdür? Bütün nəticəni yaddaşda saxlamağı istəyirsiniz?
  • Subprocess hələ də işləyərkən bəzi çıxışınızı oxumaq istəyirsiniz?
  • Nəticə kodlarına ehtiyacınız varmı?
  • Bir proses olan ruby ​​obyektinə ehtiyacınız var və onu tələbatınız ilə öldürməyə imkan verirsiniz?

Sadə backlinks (``), sistem () və IO.popen dən Kernel.fork / Kernel.exec -a bir şeyə ehtiyac ola bilər, IO.pipeIO.select istifadə IO.select .

Əgər subprocess çox uzun sürərsə, siz qarışıqda vaxtını da programlaya bilərsiniz.

Təəssüf ki, çox asılıdır .

23
07 авг. Nick Brosnahan tərəfindən verilmiş cavab 07 Avqu 2008-08-07 08:10 '08 saat 08:10 'da 2008-08-07 08:10

Digər seçimdir:

Zaman:

  • stdrre kimi stdout lazımdır
  • Open3 / Open4 istifadə edə bilməyəcəklər (onlar NetBeans'a Mac'lerimdə istisnalar atırlar, niyə bilmirəm)

Shell redirection istifadə edə bilərsiniz:

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

Sintaksis 2>> , MS-DOS'un ilk günlərindən bu yana Linux , Mac və Windows çalışır.

20
16 июня '10 в 5:13 2010-06-16 05:13 Cavab jg-faustus tərəfindən verilir 16 iyun 'da 5:13 2010-06-16 05:13

Mən mütləq bir Ruby mütəxəssisi deyiləm, amma bunu edəcəyəm:

 $ irb system "echo Hi" Hi => true 

Siz həmçinin aşağıdakı kimi işlər görməlisiniz:

 cmd = 'ls' system(cmd) 
18
05 авг. Steve Willard tərəfindən verilmiş cavab 05 Av 2008-08-05 16:24 '08 at 4:24 pm 2008-08-05 16:24

Yuxarıdakı cavablar artıq olduqca böyükdür, amma həqiqətən də aşağıdakı yekun məqaləsini bölüşmək istəyirəm: " Ruby-də konsol əmrlərini açmaq üçün 6 yol "

Əsasən, bu deyir:

Kernel#exec :

 exec 'echo "hello $HOSTNAME"' 

system$? :

 system 'false' puts $? 

Arka qisimlər (`):

 today = `date` 

IO#popen :

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

Open3#popen3 - stdlib:

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

Open4#popen4 - gemstone:

 require "open4" pid, stdin, stdout, stderr = Open4::popen4 "false" # => [26327, #<IO:0x6dff24>, #<IO:0x6dfee8>, #<IO:0x6dfe84>] 
12
07 июня '13 в 5:07 2013-06-07 05:07 cavab 07.07.2013 tarixində 5:07 2013-06-07 05:07 tarixində verilir

Bəs həqiqətən "ən yaxşı" cavabdeh bir not üçün ehtiyac varsa.

Birincisi, Ruby kabuğu çağırdığında adətən, /bin/sh deyil, Bash deyil. Baş sintaksisi bütün sistemlər üçün /bin/sh tərəfindən dəstəklənmir.

Bash istifadə etmək istəyirsinizsə, istənilən zəng üsulu daxilində bash -c "your Bash-only command" daxil edin.

quick_output = system("ls -la")

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

Yoxlamaq üçün:

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

Yoxsa mövcud skript faylını (məsələn, script_output = system("./my_script.sh") ) istifadə edirsinizsə, Ruby script_output = system("./my_script.sh") etməlidir, amma həmişə system("bash ./my_script.sh") istifadə edə bilərsiniz system("bash ./my_script.sh") baxmayaraq ki, /bin/sh /bin/bash dan kiçik bir yük oluna bilər, ehtimal etməyəcəksiniz.

10
02 июня '17 в 23:14 2017-06-02 23:14 Cavab verilir dragon788 02 iyun '23 saat 23:14 2017-06-02 23:14

Perl-də bənzər (`) ifadələrindən də istifadə edə bilərsiniz:

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

Sadə bir şey lazım olsa rahatdır.

Istifadə etmək istədiyin üsulu nə etməyə çalışdığınıza bağlıdır; Müxtəlif üsullarla daha ətraflı məlumat üçün sənədləri nəzərdən keçirin.

7
05 авг. Cavab Rufo Sanchez 05 avqustda verilir. 2008-08-05 16:57 '08 at 4:57 2008-08-05 16:57

Bunu etmək üçün ən asan yol

 reboot = `init 6` puts reboot 
6
30 марта '17 в 21:13 2017-03-30 21:13 Cavab Alex Lorsung tərəfindən 30 Mart 'da 21:13' də veriləcək, 2017-03-30 21:13

Göstərilən əmri yerinə yetirmək üçün arxa prosesi yaratmaq üçün spawn əmrini unutma. Hətta Process sinifini və qaytarılmış pid istifadə etməyi də gözləmək olar:

 pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2") Process.wait pid pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'") Process.wait pid 

Doc deyir: bu üsul # #system , amma komandanın başa çatmasını gözləmir.

5
04 нояб. Cavab MonsieurDart tərəfindən verilmişdir 04 noyabr. 2015-11-04 18:04 '15 at 18:04 2015-11-04 18:04

Bunu bir neçə yolla əldə edə bilərik.

Kernel#exec istifadə edərək, bu əmri yerinə yetirdikdən sonra heç bir şey olmaz:

 exec('ls ~') 

backticks or %x

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

Kernel#system komutunu istifadə edərək, uğurla tamamlandığında, false verdiyi təqdirdə true false və əmr bir səhvlə başa nil qaytarır:

 system('ls ~') => true 
5
19 февр. Cavab verilib 19 fevral. 2012-02-19 21:07 '12 at 21:07 2012-02-19 21:07

Cavabdan istifadə edərək və cavabda Mihai ilə əlaqə qurarkən, bu tələblərə cavab verən funksiyanı birləşdirirəm:

  • Sehrli şəkildə STDOUT və STDERR ələ keçirir, belə ki, mənim scriptimin konsoldan işlədiyi zaman "sızdırılmır".
  • Dəyərlərinizi bir sıra kimi qabağa keçməyə imkan verir, buna görə xilas olmaqdan narahat olmaq lazım deyil.
  • Komanda çıxış statusunu tutaraq, səhv baş verdikdə aydın olur.

Bonus olaraq, bu da kabuk komutunun müvəffəqiyyətlə tamamlandığı və STDOUT-ə bir şey qoyduğu hallarda STDOUT-ə də qayıdacaqdır. Beləliklə, bu cür hallarda sadəcə qayıdır olan system fərqlidir.

Bundan sonra kod gəlir. Xüsusi system_quietly funksiyası:

 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" 
5
21 февр. Cavab Ryan Tate tərəfindən verilir 21 fevral. 2012-02-21 02:36 '12 saat 02:36 'da 2012-02-21 02:36

Normal halda olduğunuzdan daha mürəkkəb vəziyyətiniz varsa ( `` ilə Kernel.spawn() burada Kernel.spawn() yoxlayın. Xarici əmrləri yerinə yetirmək üçün nəzərdə tutulan ən ümumi / tam özellikli Ruby marginı bu görünür.

məsələn. Bunu istifadə etmək üçün istifadə edə bilərsiniz:

  • proses qrupları yaratmaq (Windows)
  • redirect, uğursuzluq, fayllarda səhv / bir-biri ilə.
  • set env vars, umask
  • əmri yerinə yetirmədən əvvəl dir
  • CPU / data / ... üçün resurs limitlərini müəyyənləşdirin ...
  • Başqa parametrlər ilə digər cavablarla edilə bilən hər şeyi etməyin, amma daha çox kodla.

Rəsmi yaqut sənədləri olduqca yaxşı nümunələrə malikdir.

 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) 
3
11 дек. Cavab Kashyap tərəfindən verilir. 2015-12-11 17:57 '15 at 17:57 2015-12-11 17:57
  • Arka planların üsulu, ruby ​​dən gövdə əmrlərini çağırmaq üçün ən asan üsuldur. Shell əmrinin nəticəsini qaytarır.

      url_request = 'http://google.com' result_of_shell_command = `curl #{url_request}` 
3
16 февр. Cavab 16 fevralda verilir . 2017-02-16 12:58 '17 at 12:58 2017-02-16 12:58

Məsələn əmr verildiyi kimi,

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

Mən bu metodun, məsələn, sistemin ("əmr") və arxa tərəfdəki komanda kimi yadda qalmadığına baxmayaraq, bu üsulla digər üsullarla müqayisədə yaxşı bir şeydir. Məsələn, qayıtma siqnalları mənə qoymağa imkan vermir "Mən bir dəyişəndə ​​işləmək istədiyim əmri çalıştırdığım komanda və sistem (" thecommand ") mənə nəticə əldə etməyə icazə vermir. Bu üsul hər ikisini də etməyə imkan verir, mənə stdin, stdout və stderr daxil olmaq imkanı verir.

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

1
19 дек. Cavab 19 dekabrda barlop verilir . 2017-12-19 08:54 '17 'də saat 8:54 ' də 2017-12-19 08:54

OS X üçün ruby ​​skriptində istifadə etdiyim sərin bir şeydir (buna görə də skriptdən istifadə edə və yeniləməni pəncərədən keçirdikdən sonra əldə edə bilərsiniz):

 cmd = %Q|osascript -e 'display notification "Server was reset" with title "Posted Update"'| system ( cmd ) 
-1
14 окт. JayCrossler tərəfindən 14 oktyabrda cavabla 2014-10-14 23:12 '14 at 23:12 2014-10-14 23:12

Əslində, bu cavab deyil, amma bəlkə də kimsə bunun faydalı olduğunu görür və bununla da bağlıdır.

Windows-da TK GUI istifadə edərkən və rubyw-dən shell əmrləri çağırmalısınız, u həmişə ikinci saniyədə görünən CMD penceresinden rahatsızlanacaq.

Bunun qarşısını almaq üçün istifadə edə bilərsiniz

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

və ya

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

Hər ikisi də 'log.txt' daxilində ipconfig çıxışını saxlayacaq, lakin heç bir pəncərə görünməyəcək.

U ssenarinizin içərisində require 'win32ole' etməlidir.

system() , exec()spawn() funksiyaları TK və rubyw istifadə edərkən bu zəhlətökən pəncərədə açılır.

-2
05 июля '18 в 15:55 2018-07-05 15:55 Cavab lucaortis tərəfindən verilir 05 iyul '08 15:55 2018-07-05 15:55

Tags haqqında suallar və ya bir sual