当超过 512 个字符时,bash heredoc 挂起

Posted

技术标签:

【中文标题】当超过 512 个字符时,bash heredoc 挂起【英文标题】:bash heredoc hangs when more than 512 characters 【发布时间】:2021-03-23 19:02:18 【问题描述】:

我的 gnu bash 脚本 GNU bash,版本 5.1.0(1)-release (x86_64-apple-darwin19.6.0) 当 macos 包含超过 512 个字符的heredoc 时,它们会挂起, 例如下面的 USAGE heredoc 有效,除非我再添加 1 个字符

cat <<'USAGE'
        --all       List all tasks, TASK_IDs will be ignored
        --name NAME Only list tasks with specified NAME
        --logs      list log messages
        --pending   Only list tasks that have not been scheduled
        --active    same as --pending
        --scheduled Only List tasks that have been scheduled, whether running or finished
        --running   Only List tasks that are currently executing / running
        --finished  Only List tasks that have been run, i.e., have finished
12345678901234567890 
USAGE

注意:没有变量扩展、引号等。只有文字。 如果我将所有文本分成多个 heredocs,它们都可以工作......但如果我将它们组合起来以创建一个 >512 个字符的 heredoc,bash 挂起 我做错了什么?

【问题讨论】:

我无法在 5.1.0(1)-release (x86_64-apple-darwin19.6.0) 上重现此内容。这是我尝试过的:1. 将脚本复制到文件foo,2. 在USAGE 之前添加一行“foobar”,3. 运行bash foo。脚本按预期将数据写入标准输出 很有趣,感谢您的反馈,但是......它在我的系统上失败了。顺便说一句,我没有发布我的 macos 版本:19.6.0 Darwin Kernel Version 19.6.0:Thu Oct 29 22:56:45 PDT 2020; root:xnu-6153.141.2.2~1/RELEASE_X86_64 x86_64 也许这就是问题所在? 此外,这些年来我收到了许多带有“USAGE”消息的 shell 脚本,直到最近才注意到这个问题。 只是回显一个字符串是多么奇怪的结构。为什么不简单地使用echo 后跟一个包含在引号中的多行字符串? 【参考方案1】:

嗯 - 问题已经消失了。可能与最近的 bash 升级有关 GNU bash,版本 5.1.4(1)-release (x86_64-apple-darwin19.6.0) 这确实对与heredoc wrt缓冲区大小相关的heredoc处理进行了更改。

【讨论】:

唉,我错了。问题仍然存在。不知道为什么前几天它似乎消失了。 你解决过这个问题吗?它刚刚开始发生在我身上。 实际上,这个问题对我来说就消失了。遇到此问题的脚本刚刚开始工作。因此,如果存在潜在问题,我无法将其隔离。【参考方案2】:

最近我也开始发生同样的事情。我认识到这不是一个非常令人满意的答案,但我刚刚切换回 bash 3.2.57(1)-release,它预装了 mac。 (我花了几个小时试图弄清楚如何使用 homebrew 回滚到早期版本的 bash,但是从 2020 年开始,这似乎不再是受支持的功能。)

我运行 chsh -s /bin/bash,将我的默认 shell 更改为 Mac 默认 bash。

然后我重新安排了我的路径,以便它在/usr/local/bin/bash 之前找到/bin/bash。 (如果脚本有#!/usr/bin/env bash shebang,它会找到旧版本。)

【讨论】:

【参考方案3】:

我也遇到了同样的问题。在一位同事的帮助下,我们在我们的一个工具中追踪到这个确切问题的一个非常奇怪的行为,当管道输入

我们的环境一样,对他有用,对我没用。

macOS Catalina 10.15.7 使用 brew 安装的 Bash Bash 版本 GNU bash,版本 5.1.8(1)-release (x86_64-apple-darwin19.6.0) 内核 Darwin 内核版本 19.6.0

当使用包含 Mac 的 Bash 时,它可以工作(GNU bash,版本 3.2.57(1)-release (x86_64-apple-darwin19),但我不能使用那个版本。

这让我们发疯了。

【讨论】:

重启解决了我的问题。这太疯狂了。抱歉,我不知道真正的原因。 您可以编辑您的问题以包含重启修复,而不是评论。【参考方案4】:

这并不是问题的真正答案,而是简化代码的建议:

echo "
        --all       List all tasks, TASK_IDs will be ignored
        --name NAME Only list tasks with specified NAME
        --logs      list log messages
        --pending   Only list tasks that have not been scheduled
        --active    same as --pending
        --scheduled Only List tasks that have been scheduled, whether running or finished
        --running   Only List tasks that are currently executing / running
        --finished  Only List tasks that have been run, i.e., have finished
12345678901234567890 "

它会做同样的事情,但方式更简单。

【讨论】:

我经常需要运行包含 heredocs 的第 3 方脚本(这是与 bash 标准输入交互的一种非常常见的方式),所以“不要使用 heredocs”并不是真正的解决方案我。上面的cat &lt;&lt; EOL ... 结构实际上更像是对问题的极简再现。 没错。此外,在 heredocs 中允许的结构在引用的文本中是不允许的,因此它们是不等价的。

以上是关于当超过 512 个字符时,bash heredoc 挂起的主要内容,如果未能解决你的问题,请参考以下文章

bash中的heredoc里面的范围,我的$ PORT变量不起作用

如何使 cat 和 grep 在 c 中的第一个和第二个管道中工作,就像 bash 中的 heredoc <<

粘贴到 ssh 终端时,bash heredoc 被损坏(随机)[重复]

如何在bash脚本中执行存储在heredoc中的curl命令?

在heredocs中着色,bash

在 Bash 的 heredoc 中将新值推送到数组