【问题标题】:Bash - seamlessly run scripts with CRLF line endingsBash - 无缝运行带有 CRLF 行尾的脚本
【发布时间】:2015-06-18 16:04:27
【问题描述】:

我正在使用 VM(在我的例子中只是 boot2docker)在 Windows 主机上运行 docker 容器。为方便起见,我的源文件是从主机文件系统映射的,因此文本文件默认使用 Windows 样式的 CRLF 行结尾而不是 Unix 样式的 LF 结尾。

当我尝试从 docker 容器运行一些 .sh 文件时,我会得到一个错误

bash: ./script.sh: /bin/bash^M: bad interpreter: No such file or directory

有没有办法告诉 bash/sh 解释器自动将 \r\n 转换为 \n 并运行文件?

当然,我可以像cat script.sh | tr -d "\r" | sh 那样做一些流水线操作,甚至为此创建一个别名,但它不会涵盖一个脚本包含另一个脚本的情况。

到目前为止,我发现的唯一可接受的解决方案是将 Git 设置为以 UNIX 格式检出源文件。

【问题讨论】:

  • 你能发帖echo $TERM吗?
  • 是标准的docker容器,echo $TERM返回dumb
  • 试试export TERM=xtermexec >/dev/tty 2>/dev/tty </dev/tty(提示来自github.com/docker/docker/issues/728

标签: windows bash docker newline


【解决方案1】:

您可以在根文件夹中的 repo 中提交一个 .gitattributes 文件,以自动告诉 Git 在签出时将 LF 行结尾应用于所有 .sh 文件,即使在 Windows 上也是如此。这样,您或其他开发人员就不必记住在您克隆存储库的每台机器上配置 Git。

# Set line endings to LF, even on Windows. Otherwise, execution within Docker fails.
# See https://help.github.com/articles/dealing-with-line-endings/
*.sh text eol=lf

【讨论】:

【解决方案2】:

对于某些脚本,解决方案 ln -s /bin/bash /bin/bash^M 将失败。
因此,创建一个脚本 /bin/bash^M 将 dos2unix 他们获得的参数并使用"$@" 运行它们。

编辑: 我使用以下 bash^M 脚本进行了尝试:

#!/bin/bash
PROG=$1
shift
dos2unix $PROG > /dev/null 2>&1
$PROG "$@"

当您的脚本包含其他带点的脚本时,这将失败,在这种情况下,您应该避免这种变通方法并使用 Unix 格式。
您说您可以以 Unix 格式结帐,或者您可以自行更改文件。
并提交到 git 中,将 unix 文件以 unix 格式存储在 git 中是一种改进。当您真的想在 windows 下编辑它们时,请在之后更改编辑器或 dos2unix 的设置。

【讨论】:

  • 这看起来很聪明!所以当我创建文件/bin/bash^M时,我会摆脱错误bash: ./script.sh: /bin/bash^M: bad interpreter: No such file or directory,但我会引入另一个错误script.sh: line 2: $'\r': command not found,其中第2行应该是空行,但解释器认为有一个名为`\ r.
  • 这就是为什么你的 bash^M 不应该直接调用 bash,而是首先 dos2unix / tr 要运行的脚本。
【解决方案3】:

我想你可以写一个脚本,比如

#!/bin/bash
#bash_run_unixified
#unixify and run in bash
dos2unix < "$1" | /bin/bash

并假设您使用适当的权限 (sudo chmod o+r,o+x) 将其保存在 /urs/local/bin/bash_run_unixified 中,那么您可以在脚本前面加上

#!/usr/local/bin/bash_run_unixified
#This script has CRLFs in it

如果你不想要这种不寻常的shebang线,你可以

$ ln -s /usr/local/bin/{bash_run_unixified,bash}

然后使用 (正如 Walter A. 所指出的,将其链接到 bash^M 也可能是个好主意)

#!/usr/bin/env bash

因为你的 shebang 行(/usr/local/bin/ 通常比/bin 更接近$PATH 的开头,所以 env 命令应该选择链接到bash_run_unixifiedbash)。

(请注意:我还没有测试过这些)

【讨论】:

    【解决方案4】:

    我拥有的最佳解决方案是确保使用能够以正确的 eol 样式直接保存的编辑器(如 Notepad++ 或 Sublime Text)。

    这样,我不必在我的 boot2docker 会话中dos2unix 任何文件。

    【讨论】:

      【解决方案5】:

      Visual Studio 代码还擅长将行结尾更改为 linux 或 windows 文件结尾

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-17
        • 1970-01-01
        • 2016-04-16
        • 2011-08-10
        • 1970-01-01
        • 2016-10-20
        • 2015-02-16
        • 2017-01-11
        相关资源
        最近更新 更多