Pokud chcete spustit externí příkaz z Ruby…
…například wkhtmltopdf pro převod HTML souboru do PDF.
Existuje několik metod Ruby, které můžete použít.
V závislosti na použité metodě dostanete různé výsledky.
Prozkoumejme tyto metody společně!
Systémová metoda Ruby
Systémová metoda Ruby je nejjednodušší způsob, jak spustit externí příkaz.
Vypadá takto:
system("ls")
Všimněte si, že system
vypíše výstup příkazu, jakmile se tak stane.
Také systém donutí váš program v Ruby čekat, dokud nebude příkaz dokončen.
Zkuste to takto:
system("sleep 2")
Jsou způsoby, jak spouštět příkazy na pozadí, jak uvidíme později.
Systém může vrátit 3 možné hodnoty:
-
true
pokud příkaz fungoval -
false
pokud příkaz vrátí chybový kód -
nil
pokud se provedení příkazu nezdaří (příkaz nebyl nalezen)
Kód stavu ukončení posledního spuštěného externího příkazu můžete získat pomocí globální proměnné $?
. Tento stavový kód vám může poskytnout více informací o tom, proč příkaz selhal.
Co je to expanze shellu?
Pokud spustíte externí příkaz pomocí system
, získáte efekt „expanze shellu“.
Expanze shellu je, když shell (sh/bash/zsh) přijme některé speciální znaky (*
, ?
a ")# "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
nebo metodu Kernel#`
.
Dělají totéž.
Tady je příklad:
`ls`
Další s %x
:
%x|ls|
Tyto dva příklady vrátí řetězec s výstupem příkazu ls
.
Všimněte si, že stále musíte čekat na dokončení příkazu, pokud jej nespustíte uvnitř vlákna.
Jak použít Fork + Exec ke spuštění externích příkazů v samostatném procesu
Forkováním se vytvoří kopie aktuálního procesu (aplikace Ruby), kterou pak můžete nahradit jiným procesem pomocí exec.
Poznámka: Metoda fork není k dispozici v systému Windows.
Jedná se o oblíbený vzor v unixovém světě.
Takto to funguje:
fork { exec("ls") }
Tento příkaz spustí ls
na jiném procesu & zobrazí jeho výstup.
Protože tento příkaz běží v jiném procesu, nebude blokovat běh vaší aplikace Ruby jako metoda system
nebo %x
.
Důležité:
Použijete-li příkaz exec
bez příkazu fork
, nahradí váš aktuální proces.
To znamená, že váš program Ruby skončí.
Jak použít metodu Popen pro obousměrnou komunikaci s externím programem
Pokud potřebujete:
- Větší kontrolu nad procesem
- Obousměrnou komunikaci
Pak je metoda IO.popen
to, co hledáte.
V následujícím příkladu pomocí metody popen spustím irb
proces, pak mu pošlu nějaký vstup & přečtu výstup.
Tady je příklad:
r = IO.popen("irb", "r+")r.write "puts 123 + 1\n"3.times { puts r.gets }r.write "exit\n"
Tato proměnná r
je IO objekt, to znamená, že z ní můžete zapisovat & číst jako z běžného souboru.
Použití popen
také znamená, že váš externí příkaz poběží ve vlastním procesu, takže ho nemusíte spouštět ve vlákně.
Ve standardní knihovně je také metoda popen3
.
Rozdíl oproti běžné popen
je v tom, že rozdělí běžné výstupní & chybové zprávy na samostatné IO objekty.
Závěr
Poznali jste různé způsoby interakce s externími příkazy v jazyce Ruby.
Dávejte si na ně pozor!
Nepředávejte do těchto příkazů žádný uživatelský vstup, pokud nechcete, aby ve vaší aplikaci Ruby vznikl problém se zabezpečením.
Předpokládám, že jste se naučili pracovat s externími příkazy.