Skambučių komandų skambinimas iš Ruby

Kaip naudoti „Ruby“ programos „shell“ komandas? Kaip aš galiu išeiti iš šių komandų į Ruby?

941
05 авг. nustatyta pagal „ CodingWithoutComments“ 05 rugpjūtis 2008-08-05 15:56 '08 at 15:56 2008-08-05 15:56
@ 20 atsakymų

Šis paaiškinimas pagrįstas mano draugo Ruby komentuotu scenarijumi . Jei norite pagerinti scenarijų, atnaujinkite jį pagal nuorodą.

Pirma, atkreipkite dėmesį, kad kai Ruby skambina į apvalkalą, ji paprastai vadina /bin/sh , o ne Bash. Kai kurios „Bash“ sintaksės nepalaiko /bin/sh visose sistemose.

Čia pateikiami būdai, kaip paleisti apvalkalo scenarijų:

 cmd = "echo 'hi'" # Sample string that can be used 
  1. Kernel#' , paprastai vadinamas „backticks“ - 'cmd'

    Tai panaši į daugelį kitų kalbų, įskaitant bash, php ir perl.

    Grąžina korpuso komandos rezultatą.

    Dokumentai: http://ruby-doc.org/core/Kernel.html#method-i-60

     value = 'echo 'hi'' value = '#{cmd}' 
  2. Integruota sintaksė, %x( cmd )

    Po x simbolio yra separatorius, kuris gali būti bet koks simbolis. Jei ribotuvas yra vienas iš simbolių ( , [ , { arba < , žodinis susideda iš simbolių iki atitinkamo uždarymo ribotuvo, įskaitant įdėtus ribotojų poras. Visuose kituose ribotuvuose literatūroje yra simbolių iki kito ribotuvo simbolio atsiradimo. Stygos #{... } .

    Grąžina korpuso komandos rezultatą, taip pat atvirkštinius žymės >

    Dokumentai: http://www.ruby-doc.org/docs/ProgrammingRuby/html/>

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

    Vykdo šią komandą subshell.

    Grąžinamas true jei komanda buvo nustatyta ir sėkmingai įvykdyta, kitaip - false .

    Dokumentai: http://ruby-doc.org/core/Kernel.html#method-i-system

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

    Pakeičia dabartinį procesą vykdydama šią išorinę komandą.

    Nėra nieko, dabartinis procesas pakeičiamas ir niekada nepertraukiamas.

    Dokumentai: 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 

Štai keletas papildomų patarimų: $? , kuri yra tokia pati kaip $CHILD_STATUS , pasiekia paskutinės sistemos, kurią vykdė sistema, būseną, jei naudojate $CHILD_STATUS , system() arba %x{} . Tada galite pasiekti „ exitstatus ir „ pid savybes:

 $?.exitstatus 

Daugiau informacijos rasite:

1210
05 авг. Atsakymas, kurį pateikė Steve Willard 05 Aug 2008-08-05 17:42 '08 at 17:42 pm 2008-08-05 17:42

Čia yra bloko schema, pagrįsta šiuo atsakymu . Taip pat žr.

border=0

2019

19 мая '16 в 20:01 2016-05-19 20:01 atsakymas duotas Ian gegužės 19, 16, 20:01 2016-05-19 20:01

Kaip man patinka, naudokite %x literal, kuris supaprastina (ir skaito!) Komandos kabučių naudojimą, pavyzdžiui:

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

Tokiu atveju failų sąrašas bus užpildytas visais dabartiniame kataloge esančiais bandymo failais, kuriuos galite apdoroti kaip tikėtasi:

 directorylist.each do |filename| filename.chomp! # work with file end 
154
05 авг. atsakymas, kurį pateikė Cynicalman 05 rugpjūtis 2008-08-05 17:08 '08 at 17:08 pm 2008-08-05 17:08

Čia yra geriausias straipsnis, mano nuomone, „Ruby“ „Shell“ scenarijų vykdymas: „ 6 būdai paleisti konsolės komandas Ruby'e .

Jei tik turite gauti išvestį, naudokite nuorodas.

Man reikėjo daugiau pažengusių dalykų, tokių kaip STDOUT ir STDERR, todėl aš naudoju Open4 akmenį. Yra visi būdai.

59
02 сент. Atsakymą pateikė Mihai A 02 Sep. 2008-09-02 14:05 '08, 14:05 val. 2008-09-02 14:05

Mano mėgstamiausia Open3

  require "open3" Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... } 
32
18 сент. anshul 18 d. atsakymas 2008-09-18 20:47 '08 at 8:47 pm 2008-09-18 20:47

Kai kurie dalykai, kuriuos reikia apsvarstyti renkantis šiuos mechanizmus:

  • Ar tiesiog norite stdout, ar jums reikia stderr? ar net atskirti?
  • Kiek didelis yra jūsų produktas? Ar norite išsaugoti visą rezultatą atmintyje?
  • Ar norite perskaityti kai kuriuos išvesties duomenis, kol subprocesas vis dar veikia?
  • Ar jums reikia rezultatų kodų?
  • Ar jums reikia rubino objekto, kuris yra procesas ir leidžia jį nužudyti pagal poreikį?

IO.pipe ir IO.select gali tekti ką nors iš paprastų IO.popen (``), sistemos () ir IO.popen iki pilno dydžio Kernel.fork / IO.select .

Jei subprocesas trunka per ilgai, taip pat galite užprogramuoti laiko trukmę mišinyje.

Deja, tai labai priklauso .

23
07 авг. atsakymas, kurį pateikė Nick Brosnahan 07 rugpjūtis 2008-08-07 08:10 '08 8:10 am. 2008-08-07 08:10

Kita galimybė:

Kai:

  • reikia stderr ir stdout
  • negali / nebus naudojamas „Open3 / Open4“ („Mac“ kompiuteryje jie išskleidžia „NetBeans“, nežinau, kodėl)

Galite naudoti korpuso peradresavimą:

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

Sintaksė 2>> veikia „ Linux“ , „Mac“ ir „ Windows“ sistemose nuo MS-DOS pradžios.

20
16 июня '10 в 5:13 2010-06-16 05:13 atsakymą pateikė jg-faustus birželio 16 d. 10 val

Aš tikrai ne Ruby ekspertas, bet tai padarysiu:

 $ irb system "echo Hi" Hi => true 

Taip pat turėtumėte turėti galimybę atlikti tokius dalykus:

 cmd = 'ls' system(cmd) 
18
05 авг. Atsakymas, kurį pateikė Steve Willard 05 Aug 2008-08-05 16:24 '08 at 4:24 pm 2008-08-05 16:24

Pirmiau pateikti atsakymai jau yra gana dideli, bet aš tikrai noriu pasidalinti šiuo santraukos straipsniu: " 6 būdai paleisti konsolės komandas Ruby "

Iš esmės tai pasakoja mums:

Kernel#exec :

 exec 'echo "hello $HOSTNAME"' 

system ir $? :

 system 'false' puts $? 

Backticks (`):

 today = `date` 

IO#popen :

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

Open3#popen3 - Open3#popen3 :

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

Open4#popen4 - brangakmenis:

 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 atsakymas pateikiamas indas „ Birželio 07“, 13 val., 05:07 2013-06-07 05:07

Jei tikrai reikia Bash, užrašą „geriausias“ atsakyme.

Pirma, atkreipkite dėmesį, kad kai Ruby skambina į apvalkalą, ji paprastai vadina /bin/sh , o ne Bash. Visoms sistemoms „Bash“ sintaksė nepalaikoma /bin/sh .

Jei reikia naudoti bash -c "your Bash-only command" į pageidaujamą skambučio metodą įterpkite „ bash -c "your Bash-only command" .

quick_output = system("ls -la")

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

Norėdami patikrinti:

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

Arba, jei naudojate esamą scenarijų failą (pvz., script_output = system("./my_script.sh") ), Ruby turėtų sekti shebang, bet visada galite naudoti system("bash ./my_script.sh") , kad įsitikintumėte ( nors gali būti nedidelė pridėtinė vertė iš /bin/sh /bin/bash , jūs tikriausiai nepastebėsite.

10
02 июня '17 в 23:14 2017-06-02 23:14 atsakymas pateikiamas dragon788 02 birželio 17 d. 23:14 2017-06-02 23:14

Taip pat galite naudoti „Backtick“ (`) teiginius, panašius į„ Perl “:

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

Patogus, jei jums reikia kažko paprasto.

Kuris metodas, kurį norite naudoti, priklauso nuo to, ką bandote daryti; Išsamesnės informacijos apie įvairius metodus rasite dokumentuose.

7
05 авг. atsakymą pateikė Rufo Sanchez 05 rug. 2008-08-05 16:57 '08 at 4:57 2008-08-05 16:57

Paprasčiausias būdas yra, pavyzdžiui:

 reboot = `init 6` puts reboot 
6
30 марта '17 в 21:13 2017-03-30 21:13 atsakymą pateikė Alexas Lorsungas kovo 30 d. 17, 21:13 2017-03-30 21:13

Nepamirškite komandų, kad sukurtumėte foninį procesą nurodytai komandai vykdyti. Jūs netgi galite laukti, kol jis baigsis naudojant „ Process klasę ir grąžintus „ 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 

Doc sako: šis metodas yra panašus į #system , tačiau jis nelaukia, kol komanda bus baigta.

5
04 нояб. Atsakymą pateikė MonsieurDart 04 lapkričio. 2015-11-04 18:04 '15, 18:04 2015-11-04 18:04

Tai galime pasiekti keliais būdais.

Naudojant Kernel#exec , atlikus šią komandą, nieko neįvyksta:

 exec('ls ~') 

backticks or %x

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

Naudodami „ Kernel#system komandą, sėkmingai atlikus, true false jei ji nepavyko, ir grąžina nil jei komanda baigia klaidą:

 system('ls ~') => true 
5
19 февр. atsakymas pateikiamas nkm 19 vasario mėn. 2012-02-19 21:07 '12 - 21:07 2012-02-19 21:07

Naudodamiesi čia pateiktais atsakymais ir atsakydami į Mihą, sujungiau šią funkciją atitinkančią funkciją:

  • Švelniai užfiksuoja STDOUT ir STDERR, todėl jie nėra „nutekėję“, kai mano scenarijus veikia iš konsolės.
  • Leidžia perduoti argumentus korpusui kaip masyvą, todėl nereikia nerimauti dėl pabėgimo.
  • Užfiksuoti komandos išėjimo būseną, todėl paaiškėja, kai įvyko klaida.

Kaip premiją, tai taip pat grįš STDOUT tais atvejais, kai korpuso komanda sėkmingai baigia (0) ir įkelia kažką į STDOUT. Taigi, tai skiriasi nuo system , kuri tokiais atvejais tiesiog grįžta true .

Toliau ateina kodas. Specifinė funkcija „ 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" 
5
21 февр. atsakymą pateikė Ryan Tate 21 vasaris. 2012-02-21 02:36 '12, 02:36 am 2012-02-21 02:36

Jei turite sudėtingesnį atvejį nei įprastas atvejis (kuris negali būti apdorojamas su `` ), tada patikrinkite čia Kernel.spawn() . Atrodo, kad tai labiausiai paplitęs / pilnas „ Ruby“ skirtumas , skirtas išorinėms komandoms vykdyti.

Pavyzdžiui. Ją galite naudoti:

  • kurti procesų grupes („Windows“)
  • peradresuoti, nepavykti, klaida failuose / tarpusavyje.
  • nustatyti env vars, umask
  • keisti režimą prieš vykdydami komandą
  • nustatyti CPU / duomenų / ... išteklių ribas
  • Atlikite viską, kas gali būti padaryta su kitais parametrais, bet daugiau kodų.

Oficialūs rubino dokumentai yra gana geri pavyzdžiai.

 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 дек. Atsakymą pateikė Kashyap, gruodžio 11 d. 2015-12-11 17:57 '15, 17:57 2015-12-11 17:57
  • „Backticks“ metodas yra paprasčiausias skambinti „shell“ komandoms iš rubino. Jis grąžina komandinės komandos rezultatus.

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

Pavyzdžiui, atsižvelgiant į komandą

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

Radau, kad nors šis metodas nėra toks įsimintinas kaip, pvz., Sistema („komanda“) arba komanda „backticks“, šis metodas yra geras dalykas, palyginti su kitais metodais. Pavyzdžiui, grįžimo signalai neleidžia man pateikti „Komanda, kurioje paleidžiu / išsaugoju komandą, kurią noriu paleisti kintamajame, ir sistema („ rekomendacija “), atrodo, neleidžia man gauti rezultatų. Nors šis metodas leidžia man daryti abu šiuos dalykus, tai leidžia man patekti į stdin, stdout ir stderr.

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 дек. Atsakymas duotas gruodžio 19 d. 2017-12-19 08:54 '17, 08:54 am. 2017-12-19 08:54

Čia yra vėsius, kurį naudoju rubino scenarijuje OS X sistemoje (todėl galiu paleisti scenarijų ir gauti atnaujinimą net po perjungimo iš >

 cmd = %Q|osascript -e 'display notification "Server was reset" with title "Posted Update"'| system ( cmd ) 
-1
14 окт. JayCrossler atsakymas spalio 14 d 2014-10-14 23:12 '14, 23:12 2014-10-14 23:12

Tiesą sakant, tai nėra atsakymas, bet galbūt kas nors tai naudinga, ir tai susiję su tuo.

Naudojant „TK GUI“ sistemoje „Windows“, ir jums reikia skambinti „shell“ komandomis iš „rubyw“, u visada bus sujaudintas CMD >

Norėdami to išvengti, galite naudoti

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

arba

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

Abu ipconfig išvestys bus saugomi „log.txt“, bet nebus rodomi >

U reikės require 'win32ole' jūsų scenarijaus viduje.

system() , exec() ir spawn() pasirodys šiame erzinančiame >

-2
05 июля '18 в 15:55 2018-07-05 15:55 atsakymą pateikė lucaortis liepos 05-18 d. 15:55 2018-07-05 15:55

Kiti klausimai apie žymes arba Ask a question