【问题标题】:Problems calling shell command from .net core Linux从 .net core Linux 调用 shell 命令时出现问题
【发布时间】:2018-07-31 09:17:23
【问题描述】:

我在从 Linux .net 核心控制台应用程序调用命令时遇到一些问题。

Sub Main()
    Dim PI As New ProcessStartInfo

    Using Proc As New Process
        With PI
            .FileName = "cat"
            .Arguments = "/etc/*-release"
            .RedirectStandardOutput = True
            .UseShellExecute = False
            .CreateNoWindow = True
        End With
        Proc.StartInfo = PI
        Proc.Start()
        PI = Nothing
        Console.Write(Proc.StandardOutput.ReadToEnd)
    End Using
End Sub

我收到此错误:

cat: '/etc/*-release': No such file or directory

如果我禁用重定向并设置 UseShellExecute = True,它会起作用,但我希望能够在我的代码中使用输出。

【问题讨论】:

  • 如果你想避免使用 shell,那么你必须复制 shell 所做的工作来扩展 /etc/*-release。不太熟悉该语言,但也许它有 Unix C glob() 函数的包装器或等价物?
  • 我并没有过多考虑到底发生了什么。我只是希望 'cat' 进行“文件搜索”而不是 shell ......但我现在看到了逻辑,谢谢。

标签: linux debian .net-core


【解决方案1】:

当你运行类似的命令时

cat /etc/*-release

linux shell(可能是bash)评估每个参数,然后使用评估的参数调用程序。简单的词对自己求值,但变量(如$SOME_ARGUMENT)和模式(如*)求值和文件名。所以 shell 真的将上面的内容评估为(假设只有一个文件):

cat /etc/os-release

所以cat 程序只得到了一个参数 - 没有像 * 这样的任何 glob。

如果您想在您的程序中模拟该行为,您需要将UseShellExecute 设置为True

或者,也许您可​​以自己进行评估。像 Directory.EnumerateFiles 这样的 API 可以让你做到这一点:

 Dim textFiles = Directory.EnumerateFiles("/etc/", "*-release")

然后您需要遍历此集合并使用确切的文件名作为您的 .Arguments 值。

编辑:但更进一步,你为什么还要尝试这样做?如果您已完整阅读该文件,为什么要致电cat。为什么不只是 Console.WriteLine() 文件本身而不是调用 cat

【讨论】:

  • 我正在制作一个管理工具,它将调用许多不同的命令,并且我创建了一个函数,以便在我想触发命令CallCMD(EXE as string, Args as strings()) as string 时调用。输出需要保存为字符串以供进一步处理。将UseShellExecute 设置为True 似乎是不可能的。 cat /etc/*-release 只是一个例子......我希望它支持我在 bash shell 中工作的任何命令。
【解决方案2】:

啊……明白了!

我只需要使用bash -c ""cat ""/etc/*-release""""

    Sub Main()
    Dim PI As New ProcessStartInfo

    Using Proc As New Process
        With PI
            .FileName = "bash"
            .Arguments = "-c ""cat ""/etc/*-release"""""
            .RedirectStandardOutput = True
            .UseShellExecute = False
            .CreateNoWindow = True
        End With
        Proc.StartInfo = PI
        Proc.Start()
        PI = Nothing
        Console.Write(Proc.StandardOutput.ReadToEnd)
    End Using
End Sub

【讨论】:

  • 不确定这些引号的真正含义,但它们看起来很古怪。您传递给-c 的字符串应该是cat /etc/*-release,没有任何额外的内部引号。在例如Python,这将是subprocess.call(['bash', '-c', 'cat /etc/*-release']),如果这有助于了解我想说的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2020-10-01
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多