C - MINGW64系统("command")与壳中的"command"不同



程序"execinput"从stdin读取输入行 并将它们存储到字符数组"缓冲区"中,然后执行以下操作:

system(buffer);

让"命令"是任何一组有效的程序、参数和 bash 语法。 理想情况下,接下来的两行将给出相同的结果(暂时忽略"命令"中任何双引号的处理):

command
echo "command" | execinput

在 bash shell 中运行的 Linux 系统上确实如此。 但是,在"Msys2 MingW 32bit"外壳中的bash中,会发生这种情况(3之后的尾随分号是故意的):

echo 1; echo 2; echo 3;
1
2
3
echo "echo 1; echo 2; echo 3;" | execinput
1 ; echo 2; echo 3;
echo "echo 1 & echo 2 & echo 3;" | execinput
1
2
3;

"&"字符是 cmd.exe 用来分隔子命令的字符。 linux系统上的最后一个命令,无论是直接在bash中还是通过system()给出:

3
1
2

在 linux bash 环境中,所有命令都是一样的,无论是直接运行还是通过execinput()中的system()运行。在MSYS2环境中,他们没有。

我相信COMSPECPATH以某种方式参与其中,但将前者设置为这样:

export COMSPEC="C:progsmsys32usrbinbash.exe -c "

而不是默认的 COMSPEC 值:

C:Windowssystem32cmd.exe

结果仍然不一样。

有人可以解释一下这里发生了什么,并希望如何使"命令"直接在 bash 命令行上以及使用system()调用时出现相同?


更多信息。 在 MSYS2 的 bash 命令行中:

echo 'set' | execinput > short.txt
echo 'bash -c "set"' | execinput > long.txt

然后比较文件内容。 主要区别在于:

  1. 长.txt有 11 个 BASH *符号加上 DIRSTACK, EUID, GROUPS, IFS, MACHTYPE, OPTERR, OPTIND, OSTYPE, PPID, SHELLOPTS,UID.
    简而言之.txt没有这些。
  2. SYSTEMROOT,COMSPEC,CONTITLE,HOMEPATH和许多其他人是 长引号.txt单引号,短引号.txt。
    字符串在其他方面是相同的。
  3. PWD在长篇上是完全linux/posix语法的.txt并且有它的根 在 MSYS2 文件系统的顶部。 PWD 采用混合语法 简而言之.txt(以 C: 开头,然后有一个/分隔的路径)并且 完整的窗口路径。
  4. PATH 长.txt以 linux/posix 语法条目开头, 根在 MSYS2 文件系统的顶部,然后是条目 比如/c/Windows/System32。 短.txt具有完整的条目 窗口语法。
  5. 长.txt SHLVL=2,短.txt SHLVL=1。

在你的问题中,你假设command代表"Bash 语法"。

但是,system()调用是在 Gnu/Linux 上调用sh,在 Windows 系统上调用cmd.exe。由不同的 shell 解释会导致传递到system()调用的两个命令行的不同结果:

echo 1; echo 2; echo 3;
echo 1 & echo 2 & echo 3;

我不知道是否有任何方法可以让system()在Windows上调用不同的命令处理器,如果COMPSPEC似乎不会影响它。

如果你可以控制execinput的源代码,我建议在那里实现一个更可移植的command执行,例如使用exec*()系统调用之一以及指向所需shell的已定义路径。

"Msys2 MingW 32bit"意味着您打开一个MSYS2 Bash shell,其中设置了路径,以便gcc解析为面向本机Win32的mingw-w64构建。本机 Win32 可执行文件与 MSYS2 Bash 无关;命令处理器cmd.exe. MSYS2 shell 只是一个开发工具。

如果打开"Msys2 MSYS2",则gcc解析为面向 MSYS2 系统的 mingw-w64 构建。您可以使用gcc -v检查目标,它会说Target: x86_64-pc-msys或类似。 我对此进行了测试,它确实按预期使用/usr/bin/bash作为命令处理器。

请注意,不同的目标使用不同的 gcc 安装;MSYS2 目标是pacman -S msys2/gcc的,本机 Win32 目标是pacman -S mingw32/mingw-w64-i686-gcc的。 它不使用通过开关选择目标的单个编译器,就像一些 gcc 构建一样。

当然,如果构建面向 MSYS2 的,则生成的可执行文件必须在 MSYS2 下运行。

最新更新