换行符问题

问题Linux 环境执行一些脚本出错,查找原因,发现是文件在Windows环境修改并上传,格式被转换为MS-Dos格式(换行符不同),这样的文件在Linux中运行会出错(shell 解释器把换行符作为一个命令的提交)。背景很久以前,老式的电传打字机使用两个字符来另起新行。回车符(CR,carriag

问题

Linux 环境执行一些脚本出错,查找原因,发现是文件在Windows环境修改并上传,格式被转换为MS-Dos格式(换行符不同),这样的文件在Linux中运行会出错(shell 解释器把换行符作为一个命令的提交)。

背景

很久以前,老式的电传打字机使用两个字符来另起新行。回车符(CR,carriage return)把滑动架移回行首 ,换行符(LF,newline)把纸上移一行 。

当计算机问世以后,存储器曾经非常昂贵。有些人就认定没必要用两个字符来表示行尾。 UNIX 用  一个字符来表示行尾。 Apple 的MacOS 9 及以前用 <CR> ,MacOS 10跟Unix一样。 MS-DOS (以及Windows) 沿用老式的<CR><LF>,即敲一下回车键,相当于同时执行了 "回车+换行"。 总结一下:

系统 中文描述 英文描述 简写 转义符 十六进制
Windows 回车换行 Carriage Return and Line Feed CRLF \\r\\n 0x0d0a (1310)
Unix/Linux/Mac OS 换行 Line Feed LF \\n 0x0a (10)

如果你把一个文件从一种系统移到另一种系统,那么你就有换行符方面的麻烦。 Windows10的记事本(notepad)能够自动识别Linux文件,但是在Linux中查看MS-DOS格式文件会发现每一行的末尾有个 ^M 字符。(^M 就是 <CR>,即回车符)。

单个文件解决办法

Linux 环境下 vim 直接编辑修改文件。

:set fileformat=unix

或者

:set ff=unix 

保存退出就解决了。

批量文件解决方案一

这是通用方案,核心逻辑是

  • 找出文件:用file命令查看文件是否有特殊换行符
  • 修改文件:dos2unix命令直接改。(也可以vi 文件修改,后面在举例)

具体例子

1. 检查文件

$ file ./test.yml 
./test.yml: ASCII text, with CRLF line terminators

输出中看到了CRLF,这是Dos文件格式的标志。

2. 下一步,文件格式转换

$ dos2unix ./test.yml 
dos2unix: converting file ./test.yml to Unix format ... 

3. 检查文件是否真的修改了格式

$ file ./test.yml 
./test.yml: ASCII text 

发现没有CRLF 标志,修改完成。

4. 把上面的命令合并,查找并修改Dos格式文件

$ find . -type f -exec file {} \; | grep CRLF | awk -F: '{print $1}' | xargs dos2unix 
dos2unix: converting file ./ansible/README.md to Unix format ... 
... 
or
$ find . -type f -exec file {} \; | grep CRLF | cut -d : -f 1 | xargs dos2unix 

批量文件解决方案二

从 7.1 版本后,dos2unix 有-i,--info参数,能够直接获取文件换行符的信息,我们能直接用这个命令来查找和替换。-ic参数表示只是打印需要转换的文件。 (MacOS 通过brew 可以安装 dos2unix version 7.4,而centos 7 和 ubuntu 16 默认只能安装版本6.0,更高版本需要自己单独下载安装包。)

$ dos2unix -i ./roy_test.yml 
      11       0       0  no_bom    text    ./roy_test.yml 
$ dos2unix -ic ./roy_test.yml 
./roy_test.yml 

上面的输出数字 11 表示有11个dos换行符。 查找并修改dos文件:

$ find . -type f -exec dos2unix -ic {} \; | xargs dos2unix 
dos2unix: converting file ./bin/Readme.txt to Unix format... 
... 

如果文件数量大,用xargs 替换 exec 更有效率,所以更好的命令是

$ find . -type f | xargs dos2unix -ic | xargs dos2unix 

Windows开发中避免换行问题

使用编辑器Visual Studio Code

这个工具的右下角的文件格式确保是LF。如果不是,就点击重新选择。

image.png

git bash 中设置默认检入检出换行符为linux(\n)风格

(为了团队更好的协作)

开启自动换行
git config --global core.autocrlf true 
git config --global core.autocrlf true 签出时将换行符转换成CRLF,签入时转换回 LF 
git config --global core.autocrlf input 签出时不转换换行符,签入时转换回 LF 
git config --global core.autocrlf false 签出签入均不转换
开启安全换行
git config --global core.safecrlf true

解释: 如果你把换行符搞乱了,在一个文件中既包含windows风格的换行符也包含unix风格换行符,那么 safecrlf 就可以发挥作用了:

git config --global core.safecrlf true 拒绝提交包含混合换行符的文件 
git config --global core.safecrlf false 允许提交包含混合换行符的文件 
git config --global core.safecrlf warn 提交包含混合换行符的文件时候给出警示

参考文档

不同平台windows、linux、mac 上换行符的问题vim下unix和dos格式转换NewLine Wikipedia

链接:https://www.jianshu.com/p/fe8ec5f5792d

Read more

容器镜像(4):镜像的常用工具箱

容器镜像(4):镜像的常用工具箱

前几篇在讲多架构镜像时已经用过 skopeo 和 crane 做镜像复制,这篇系统整理这两个工具的完整能力,同时介绍几个日常操作镜像时同样好用的工具。 一、skopeo:不依赖 Daemon 的镜像瑞士军刀 skopeo 的核心价值是绕过 Docker daemon,直接与 Registry API 交互。上一篇用它做镜像复制和离线传输,但它的能力远不止于此。 1.1 安装 # Ubuntu / Debian sudo apt install -y skopeo skopeo --version # skopeo version 1.15.1 1.2 inspect:免拉取检查镜像元数据 docker inspect 需要先把镜像拉到本地,skopeo inspect 直接向 Registry

容器镜像(3):多架构镜像构建

容器镜像(3):多架构镜像构建

一、什么是多架构镜像 1.1 OCI Image Index 上一篇介绍了单平台镜像的结构:一个 Manifest 指向 Config 和若干 Layer blob。多架构镜像在此之上多了一层——OCI Image Index(也叫 Manifest List),是一个轻量的索引文件,把多个单平台 Manifest 组织在一起: $ docker manifest inspect golang:1.22-alpine { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests&

容器镜像(2):containerd 视角下的镜像

容器镜像(2):containerd 视角下的镜像

一、为什么需要了解 containerd 如果你只用 docker run 跑容器,从来不关心底层,那可以不了解 containerd。但如果你在用 Kubernetes,或者想真正理解"容器运行时"是什么,containerd 是绕不开的。 事实上,当你执行 docker run 的时候,containerd 早就在后台悄悄工作了——Docker 从 1.11 版本开始,就把核心运行时剥离出来交给 containerd 负责。 1.1 Docker 的架构演变 早期的 Docker(1.10 及之前)是一个"大一统"的单体程序:一个 dockerd