Om du vill köra ett externt kommando från Ruby…
…som till exempel wkhtmltopdf för att konvertera en HTML-fil till en PDF.
Det finns några Ruby-metoder som du kan använda.
Avhängigt av vilken metod du använder kommer du att få olika resultat.
Låt oss utforska dessa metoder tillsammans!
Rubys systemmetod
Rubys systemmetod är det enklaste sättet att köra ett externt kommando.
Det ser ut så här:
system("ls")
Bemärk att system
skriver ut kommandots utdata när det händer.
Också systemet kommer att få ditt Ruby-program att vänta tills kommandot är klart.
Prova så här:
system("sleep 2")
Det finns sätt att köra kommandon i bakgrunden som vi kommer att se senare.
Systemet kan returnera 3 möjliga värden:
-
true
om kommandot fungerade -
false
om kommandot returnerar en felkod -
nil
om utförandet av kommandot misslyckas (kommandot hittas inte)
Du kan få fram utgångsstatuskoden för det senaste externa kommandot som du körde med den globala variabeln $?
. Denna statuskod kan ge dig mer information om varför kommandot misslyckades.
Vad är skalutvidgning?
När du kör ett externt kommando med system
får du ”skalutvidgningseffekten”.
Skalutvidgning är när skalet (sh/bash/zsh) tar några specialtecken (*
, ?
och ")# "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
eller metoden Kernel#`
.
De gör samma sak.
Här är ett exempel:
`ls`
Ett annat med %x
:
%x|ls|
De här två exemplen returnerar en sträng med utdata från ls
-kommandot.
Bemärk att du fortfarande måste vänta på att kommandot ska bli färdigt om du inte kör det inuti en tråd.
Hur du använder Fork + Exec för att köra externa kommandon i en separat process
Fork gör en kopia av din nuvarande process (din Ruby-app) och sedan kan du ersätta den kopian med en annan process med hjälp av exec.
Notera: Fork-metoden är inte tillgänglig i Windows.
Detta är ett populärt mönster i Unix-världen.
Så här fungerar det:
fork { exec("ls") }
Detta kommer att köra ls
på en annan process & visa dess utdata.
Då det här kommandot körs i en annan process blockerar det inte din Ruby-app från att köras, som system
-metoden eller %x
.
Viktigt:
Om du använder exec
utan fork
kommer du att ersätta din nuvarande process.
Detta innebär att ditt Ruby-program avslutas.
Hur man använder Popen-metoden för tvåvägskommunikation med ett externt program
Om du behöver:
- Mer kontroll över processen
- Tvåvägskommunikation
Då är IO.popen
-metoden vad du söker.
I följande exempel använder jag popen-metoden för att starta en irb
process, sedan skickar jag lite indata till den & och läser utdata.
Här är exemplet:
r = IO.popen("irb", "r+")r.write "puts 123 + 1\n"3.times { puts r.gets }r.write "exit\n"
Den här r
variabeln är ett IO-objekt, det betyder att du kan skriva & läsa från den som en vanlig fil.
Användning av popen
innebär också att ditt externa kommando körs i en egen process, så du behöver inte köra det i en tråd.
Det finns också en popen3
-metod i standardbiblioteket.
Skillnaden mot den vanliga popen
är att den delar upp vanliga utdata &felmeddelanden i separata IO-objekt.
Slutsats
Du har lärt dig om de olika sätt som du kan interagera med externa kommandon i Ruby.
Var försiktig med dessa!
Passa inte in någon form av användarinmatning i dessa kommandon om du inte vill ha ett säkerhetsproblem i din Ruby-app.