defmodule ProxmoxAgent.Shell do @moduledoc """ Thin wrapper over System.cmd for testability. Collectors accept an optional :runner function of this shape so tests can inject fixture-backed fakes. """ @type result :: {:ok, String.t()} | {:error, term()} @spec run(String.t(), [String.t()]) :: result def run(command, args) do start = System.monotonic_time(:microsecond) result = do_run(command, args) duration_us = System.monotonic_time(:microsecond) - start ProxmoxAgent.Diagnostics.log_command(command, args, result, duration_us) result end defp do_run(command, args) do try do case System.cmd(command, args, stderr_to_stdout: true) do {output, 0} -> {:ok, output} {output, code} -> {:error, {:nonzero_exit, code, output}} end rescue e in ErlangError -> case e.original do :enoent -> {:error, {:enoent, command}} other -> {:error, {:system_error, other}} end end end end