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.