Ruby, Różnica między exec, systemem a% x () lub Backticks


370

Jaka jest różnica między następującymi metodami Ruby?

exec, systemI %x()czy backticks

Wiem, że są one używane do programowego wykonywania poleceń terminalowych za pośrednictwem Ruby, ale chciałbym wiedzieć, dlaczego istnieją trzy różne sposoby, aby to zrobić.


1
Te i wiele innych poleceń zostały dość dobrze wyjaśnione w dokumentacji: backticks systemu exec
zetetic

1
Istnieje świetny artykuł Ruby Quicktips na ten temat: Wykonywanie poleceń powłoki .
Simon Perepelitsa

6
Ponieważ ktoś właśnie wykopał ten stary wątek, „Praca z procesami uniksowymi” jest doskonałą książką dla rubinów zainteresowanych tematem: workingwithunixprocesses.com
Michael Kohl

1
Dziwi mnie, że żadna z odpowiedzi nie wspomina sh.
Dennis,

@Dennis Kiedy zadawałem to pytanie, ruby ​​1.9.3 * nie zostało wydane.
Mr. Black

Odpowiedzi:


411

system

systemMetoda nazywa program systemowy. Musisz podać polecenie jako argument ciągu dla tej metody. Na przykład:

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

Program wywołany użyje prąd STDIN, STDOUTa STDERRobiekty z programu Ruby. W rzeczywistości faktyczna wartość zwracana to albo true, falsealbo nil. W przykładzie data została wydrukowana przez obiekt IO obiektu STDIN. Metoda zwróci, truejeśli proces zakończy się ze statusem zerowym, falsejeśli proces zakończy się ze statusem niezerowym i niljeśli wykonanie się nie powiedzie.

Innym efektem ubocznym jest to, że zmienna globalna $?jest ustawiona na Process::Statusobiekt. Ten obiekt będzie zawierał informacje o samym wywołaniu, w tym identyfikator procesu (PID) wywoływanego procesu i status wyjścia.

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

Backticks

Backticks (``) wywołują program systemowy i zwracają jego wynik. W przeciwieństwie do pierwszego podejścia, polecenie nie jest przekazywane przez ciąg znaków, ale przez umieszczenie go w parze backticks.

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

Zmienna globalna $?jest również ustawiana za pomocą strzałek wstecznych. Za pomocą backticksa można również użyć interpolacji łańcuchów.

% x ()

Korzystanie %xjest alternatywą dla stylu backticks. Zwróci również wynik. Podobnie jak jego krewni %wi %q(między innymi), dowolny ogranicznik będzie wystarczający, o ile pasują do niego ograniczniki. Oznacza to %x(date), %x{date}i %x-date-wszystkie są synonimami. Podobnie jak backticks %xmogą korzystać z interpolacji łańcuchów.

exec

Przy użyciu Kernel#execbieżącego procesu (skryptu Ruby) zostaje zastąpiony procesem wywoływanym przez exec. Metoda może przyjąć ciąg jako argument. W takim przypadku łańcuch będzie podlegał rozszerzeniu powłoki. W przypadku użycia więcej niż jednego argumentu pierwszy służy do wykonania programu, a następujące argumenty są podawane jako argumenty programu, który ma zostać wywołany.

Open3.popen3

Czasami wymagane informacje są zapisywane na standardowe dane wejściowe lub standardowe błędy i trzeba je również kontrolować. Tutaj Open3.popen3przydaje:

require 'open3'

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

3
A dla bardziej precyzyjną kontrolę, jak uchwyty połączeń STDIN, STDOUT, STDERR, należy rozważyć Open3.popen3zamiast; np. patrz stackoverflow.com/a/10922097/258662
cboettig

1
Dziękuję za wspomnienie, że backticks obsługują interpolację łańcuchów, co rozwiązało mój problem.
adg

244

Oto schemat blokowy oparty na tej odpowiedzi . Zobacz także: używanie scriptdo emulacji terminala .

wprowadź opis zdjęcia tutaj


3
To nie jest takie proste. W moim przypadku „było OK (i trzeba) blokować aż do zakończenia procesu”, a następnie użyć popen3 do sprawdzenia wyjść STDOUT / STDERR.
Nakilon,

Zawsze możesz wywołać nieblokujące wywołanie (efektywnie) bloku, zawijając je w pętli while. Nie można tak łatwo wykonać połączenia blokującego w połączenie nieblokujące.
Ian

106

Robią różne rzeczy. execzastępuje bieżący proces nowym procesem i nigdy nie powraca . systemwywołuje inny proces i zwraca jego wartość wyjściową do bieżącego procesu. Użycie backticks wywołuje inny proces i zwraca wynik tego procesu do bieżącego procesu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.