Ha egy külső parancsot akarunk futtatni Rubyból…
…mint például a wkhtmltopdf egy HTML fájl PDF-be való konvertálásához.
Van néhány Ruby módszer, amit használhatunk.
Az alkalmazott módszertől függően különböző eredményeket kapunk.
Vizsgáljuk meg együtt ezeket a módszereket!
A Ruby rendszermódszer
A Ruby rendszermódszer a legegyszerűbb módja egy külső parancs futtatásának.
Ez így néz ki:
system("ls")
Megjegyezzük, hogy a system
kiírja a parancs kimenetét, amint az történik.
A rendszer továbbá arra készteti a Ruby programodat, hogy várjon, amíg a parancs befejeződik.
Kipróbáld ezt:
system("sleep 2")
A parancsok háttérben történő futtatásának is vannak módjai, mint később látni fogjuk.
A rendszer 3 lehetséges értéket adhat vissza:
-
true
ha a parancs működött -
false
ha a parancs hibakódot ad vissza -
nil
ha a parancs végrehajtása sikertelen (parancs nem található)
A $?
globális változóval megkaphatjuk a legutóbb futtatott külső parancs exit status kódját. Ez az állapotkód további információt adhat arról, hogy a parancs miért sikertelen.
Mi az a Shell bővítés?
Ha egy külső parancsot futtatsz a system
segítségével, akkor megkapod a “shell bővítés” hatást.
A shell bővítés az, amikor a shell (sh/bash/zsh) néhány speciális karaktert (*
, ?
és ")# "best"
This will not change the current environment of your Ruby application.
%x / Kernel#`
If you want to get the output from the command you're running, instead of displaying it then you can use %x
vagy a Kernel#`
módszert.
Ezek ugyanazt teszik.
Itt egy példa:
`ls`
Egy másik a %x
-val:
%x|ls|
Ez a két példa egy stringet ad vissza a ls
parancs kimenetével.
Megjegyezzük, hogy még mindig várnunk kell a parancs befejezésére, hacsak nem egy szálon belül futtatjuk.
How to Use Fork + Exec To Run External Commands On a Separate Process
Forking készít egy másolatot az aktuális folyamatról (a Ruby alkalmazásról), majd ezt a másolatot egy másik folyamattal helyettesítheti az exec segítségével.
Megjegyzés: A fork módszer nem elérhető Windows alatt.
Ez egy népszerű minta a Unix világában.
Íme, hogyan működik:
fork { exec("ls") }
Ez a ls
egy másik folyamat & kimenetének megjelenítésével
Mivel ez a parancs egy másik folyamatban fut, nem fogja blokkolni a Ruby alkalmazásod futását, mint a system
módszer vagy a %x
.
Fontos:
Ha a exec
parancsot fork
nélkül használod, akkor lecseréli az aktuális folyamatodat.
Ez azt jelenti, hogy a Ruby programod véget ér.
Hogyan használd a Popen módszert a kétirányú kommunikációhoz egy külső programmal
Ha szükséged van:
- több kontrollra a folyamat felett
- kétirányú kommunikációra
akkor a IO.popen
módszer az, amit keresel.
A következő példában a popen metódussal elindítok egy irb
folyamatot, majd küldök neki némi bemenetet & kiolvasom a kimenetet.
Itt a példa:
r = IO.popen("irb", "r+")r.write "puts 123 + 1\n"3.times { puts r.gets }r.write "exit\n"
Ez a r
változó egy IO objektum, ez azt jelenti, hogy írni & olvasni lehet róla, mint egy hagyományos fájlból.
A popen
használata azt is jelenti, hogy a külső parancsod saját folyamatában fog futni, így nem kell egy szálon futtatnod.
A standard könyvtárban is van egy popen3
módszer.
A különbség a szokásos popen
-hoz képest az, hogy a szokásos kimeneti & hibaüzeneteket külön IO objektumokra osztja.
Következtetés
Megtanultad, hogy milyen különböző módon léphetsz kapcsolatba külső parancsokkal a Ruby-ban.
Vigyázz ezekkel!
Ne adj át semmiféle felhasználói bemenetet ezekbe a parancsokba, hacsak nem akarsz biztonsági problémát a Ruby alkalmazásodban.