Windows 中的 Bash 使用:“无法发送空消息”错误

Windows 中的 Bash 使用:“无法发送空消息”错误

因此,我需要一种方法来从 Windows 机器向 discord 发送一些 webhook,在 Linux 中这样做没有问题curl,所以我从 Windows 应用商店将 Ubuntu 18 LTS 安装了到机器上并尝试了一下。

当我在 Windows 中使用相同的命令时,问题就出现了:

bash -c "curl -H "Content-Type:application/json" -X POST -d '{"x": "x", "content": "hello"}' https://discordapp.com/api/webhooks/536660752111763477/zkW73A97-TNJVcH3xMCK0GMHEkwqKNWSfslA0WxxxxxxMYOLTRi6UMXYR_QLDCfxIJ_d"

我收到此错误:

{"code": 50006, "message": "Cannot send an empty message"}

该字符串中什么内容是 Windows 不喜欢的?

我弄乱了空格和其他东西,但只破坏了更多。

答案1

脚本中的问题实际上可以通过 Ask Ubuntu 语法突出显示非常清楚地显示出来 - 正如您在答案中所看到的,"x"帖子中的 被涂成黑色,因为它位于双引号字符串之外,而该字符串是 参数的值-cbash这个问题在您的整个代码中重复出现。

字符串在 shell 中的工作方式是,双引号是一种让多个单词(即包含空格的字符序列)在 shell 中显示为单个单词的方法。然后,shell 将这些单词按原样(不带双引号)传递给程序运行。您还可以通过将文本挤压在一起而不带空格,使文本聚集成同一个单词。

因此以下命令对于 shell 来说都是相同的,并且会显示相同的输出:

  • echo 123
  • echo "1"23
  • echo "1"2"3"
  • echo "1"'2'"3"

在所有情况下都echo只会看到文本“ 123”(最后一个我用单引号引起来,对于很多效果来说,其行为是相同的。

考虑到这一点,让我们分析一下您的脚本行:

bash -c "curl -H "Content-Type:application/json" -X POST -d '{"x": "x", "content": "hello"}' https://discordapp.com/some/path"

我们可以看到,您将大量代码bash作为-c参数传递,即“要运行的命令”。因此bash将使用两个参数运行 - 第一个是-c,第二个是应被视为“命令”的所有文本。第二个参数使用双引号字符串(是的,复数)对一些空格和其他 shell 字符进行编码,以便将它们按原样传递给“要运行的命令”参数。

让我们手动执行 shell 所做的事情来理解第二个参数,通过将所有“单词”转换为经典编程语言字符串数组:

var a = [
"-c",
"curl -H " + "Content-Type:application/json" + " -X POST -d '{" + "x" + 
  ": " + "x" + ", " + "content" + ": " + "hello" + 
  "}' https://discordapp.com/some/path"
]

然后 shell 将解析字符串列表并执行 bash:

execve("bash", "-c", "curl -H Content-Type:application/json -X POST -d '{x: x, content: hello}' https://discordapp.com/some/path");

如您所见,JSON POST 负载中不再有双引号:它们被 shell 删除,以尝试理解哪些字符串构成了第二个参数。这会导致负载无效,服务器认为您没有提供输入。

顺便说一句:根据我的经验 - 你刚才所展示的是对 shell 转义如何工作的首要误解,所以不要为此感到难过 - 每个人都在这样做;-)

如果你想加双引号,你想做什么里面双引号字符串的另一种方法是“转义”它们 - 使 shell 不将它们视为特殊字符,而只是字符串文本的一部分。有两种主要方法可以做到这一点:

  1. 利用 shell 中的字符串实际上不需要引用的事实,字符串可以是没有空格的单词串在一起,也可以是没有空格的多个带引号的字符串串在一起。所以它看起来像这样:"curl -H "'"'"Content-Type:application/json"'"'" ..."。您可以看到,我们理解双引号实际上终止了从开头开始的字符串,而不是仅仅放置双引号,而实际上它不是输入的一部分,并且在 shell 看到输入结束(由于空格)之前,我们立即开始一个新字符串,这个字符串由单引号分隔 - 仅包含双引号字符,依此类推 - 这实际上类似于echo第一个示例中的最后一个命令。
  2. 使用反斜杠使内部双引号字符不被视为字符串分隔符 - 将它们从解析中转义:"curl -H \"Content-Type:application/json\" -X...

我个人比较喜欢第一种方法。

相关内容