Po dłuższej przerwie od blogowania zacznę na rozgrzewkę od przyjemnego i krótkiego tematu. Pokaże jak uruchomić polecenie powłoki systemowej bash w .NET Core na Ubuntu. Na podstawie przedstawionej metody będzie można w analogiczny sposób uruchomić inny zewnętrzny program w C#.
Process
Do rozpoczęcia procesu (uruchomienia polecania bash) zostanie wykorzystana metoda Start klasy Process z przestrzeni System.Diagnostics. Klasa Process odpowiada za dostęp do procesów lokalnych i zdalnych. W ramach instancji klasy Process mamy możliwość uruchamiania, zatrzymywania, kontrolowania i monitorowania procesu aplikacji.
Bash
Na początek należy sprawdzić ścieżkę do powłoki bash, którą przekażemy do właściwości FileName w ProcessStartInfo. Instancja ProcessStartInfo określa zbiór wartości, które są używane podczas uruchamiania procesu.
which bash
Po wykonaniu polecenia wypisało mi wartość /bin/bash na terminal. W celu prezentacji zaimplementowałem metodę ExecuteCommand w klasie Bash. Możemy także zamiast poniższej metody zaimplementować np. extension method dla stringa.
using System.Diagnostics; public static class Bash { public static (string output, string errorMsg) ExecuteCommand(string command) { var startInfo = new ProcessStartInfo { FileName = "/bin/bash", Arguments = $"-c \"{command}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; string output = null, errorMsg = null; using (var process = new Process() { StartInfo = startInfo}) { process.Start(); output = process.StandardOutput.ReadToEnd(); errorMsg = process.StandardError.ReadToEnd(); process.WaitForExit(); } return (output, errorMsg); } }
W bashu zostanie użyta opcja -c, która pozwala przekazać polecenie do wykonania, jako argument. W celu przechwycenie odpowiedzi/błędu i przekierowaniu na wyjście, należy w instancji ProcessStartInfo ustawić parametry RedirectStandardOutput i RedirectStandardError na wartość true. Zobaczmy jak to wygląda w praktyce. Do weryfikacji utworzyłem prostą aplikację konsolową w .NET Core i wywołam dwa polecenia. Pierwsze polecenie ma zwrócić status usługi proftpd (zakończy się sukcesem), a drugie polecenie ma zatrzymać nieistniejącą usługę abc (w tym przypadku otrzymamy błąd na wyjściu).
using System; using System.Collections.Generic; class Program { static void Main(string[] args) { var bashCommands = new List() { "service proftpd status", "service abc stop", }; foreach (var command in bashCommands) { var result = Bash.ExecuteCommand(command); if(String.IsNullOrEmpty(result.errorMsg) == false) { Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine(result.errorMsg); }; if(String.IsNullOrEmpty(result.output) == false) { Console.ForegroundColor = ConsoleColor.DarkBlue; Console.WriteLine(result.output); }; } Console.ReadKey(); } }
Czas teraz na sudo dotnet run i otrzymujemy poniższy wynik na terminalu.

Miało być konkretnie, to czas w tym miejscu zakończyć wpis merytoryczny. Na koniec dodam, że kolejny wpis jeszcze w tym tygodniu. Zapraszam do śledzenia i odwiedzin bloga.