Windows脚本在Linux无法运行?换行符、权限与Shebang的跨平台排障指南
2026/9/16 5:05:16 网站建设 项目流程

1. 同样一段脚本,Windows写得爽,Linux跑得懵:先搞清楚问题长什么样

我在运维岗上见过太多这样的场景:开发在 Windows 上写了个部署脚本,本地跑得好好的,一旦丢到 Linux 服务器上,要么报command not found,要么报syntax error: unexpected end of file,更诡异的是有些脚本连报错都不给,执行结果却跟预期完全对不上。标题里这句话——“Windows 下编写的脚本无法在 Linux 中运行”——本身是个非常笼统的描述,但落到真实环境里,它背后往往藏着七八种完全不同的病因。这篇文章我就把这几年踩过的坑、排查过的现场,以及最终沉淀下来的一套处理流程,从头到尾捋一遍。

先说结论:绝大多数问题出在三个地方——换行符、解释器声明、以及执行权限。这三样东西在 Windows 下几乎不会被注意到,因为 Windows 本身就不按 Linux 那套逻辑来。换行符是头号杀手,我统计过自己经手的跨平台脚本问题,大概有七成以上跟它有关;剩下的两成多才是解释器差异、编码 BOM、路径分隔符这类边角料。所以你不用急着怀疑自己写的语法有问题,先按照下面这套路径走一遍,九成场景十分钟内能定位到根因。

不过说句实话,真正让人头疼的不是“跑不了”本身,而是它跑起来的姿势千奇百怪。有的脚本第一行就报错,有的运行到一半突然抽风,有的结果不对但完全不报错。所以这篇文章我不想只给你几个命令就完事,我会把每个症状背后的原理也讲透。只有理解了“为什么”,遇到没见过的新报错时你才能举一反三。

1.1 最常见的两类报错现场

先还原一下最典型的两个现场,你看看自己中过哪个。

现场一:把 Windows 里写好的.sh文件通过 FTP 或者 U 盘拷到 Linux,执行./deploy.sh,终端直接甩出来:

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

这个^M就是罪魁祸首。它是回车符(Carriage Return,ASCII 13)在终端里的显示形式。Linux 下的 bash 在解析脚本第一行#!/bin/bash时,读到的其实是#!/bin/bash\r,也就是路径末尾多了一个回车字符。它去/bin/bash\r这个路径找解释器,当然找不到。

现场二:报错形式变成:

./test.sh: line 3: $'\r': command not found syntax error near unexpected token `$'\r'`

这个场景通常是脚本里的解释器声明没有换行符污染,但后续代码行末尾全带着\r。bash 在解析到回车符时,把它当成了一个命令或者语法单元,于是要么说$'\r': command not found,要么在解析 if/for 这类语法结构时报syntax error near unexpected token。有次我帮同事看一个部署脚本,他坚持说“代码在 Windows 上跑得好好的”,我让他执行一下cat -A script.sh,看到每行结尾都是^M$,他立刻沉默了。

1.2 为什么“看起来一样”的脚本,行为却完全不同

这里有个特别容易让新手困惑的点:你用 Notepad++ 或者 VSCode 打开同一个脚本文件,Windows 和 Linux 下看到的字符内容完全一样,肉眼根本看不出区别。原因很简单,回车符和换行符都是不可见字符。Windows 文本文件用\r\n(回车+换行)表示一行结束,Linux/Unix 只用\n(换行)。这个差异最早可以追溯到电传打字机时代——\r是把打印头移回行首,\n是把纸往上滚一行。Windows 继承了老式 DOS 的做法两个都用,Linux 则简化成只需要换行。

更麻烦的是,你把一个 Linux 的脚本用 Windows 记事本打开再保存一下,它也会悄悄把换行全部转成\r\n。也就是说,哪怕你最初在 Linux 上写好了脚本,只要中间经过一次 Windows 编辑器的“无意识转换”,再拷回去照样跑不了。所以这不是一个“一次性”的问题,而是一个会反复出现的兼容性问题,你必须在开发和编辑环节就把它管住。

2. CRLF和LF:99%的跨平台脚本问题都出在这个看不见的字符上

既然换行符是第一大杀手,那我们就把它单独拎出来,彻底讲明白。文本文件里每一行的结尾,在 Windows 下是\r\n两个字符,在 Linux 下是\n一个字符。\r全称 Carriage Return,对应十六进制0x0D\n全称 Line Feed,对应十六进制0x0A。这俩的称呼也经常被搞混——Linux 下管\n叫换行符,Windows 下经常把回车换行合在一起叫;而老式的 Mac(macOS 9 及以前)用的是单独的\r,这个虽然现在很少见了,但在一些古董文本文件里还能碰到,遇到的话同样会导致解析错乱。

2.1 一个回车符引发的血案

要真正理解为什么\r能让 bash 直接崩溃,你得站在解释器的角度想问题。Shell 是一种行解释器:它按行读取脚本,每读一行就做词法分析。词法分析阶段,\r本身不是一个合法的命令分隔符,也不是空字符,于是 bash 在遇到$'\r'的时候会把它当作一个 token 去尝试解释。在命令替换、变量赋值、函数定义这些场景里,这个额外的 token 就会让解析器彻底懵掉。

举个例子。假设你的脚本里有这一行:

if [ -f "/etc/passwd" ]; then echo "exists" fi

如果每行结尾都是\r\n,那么 bash 实际读到的是:

if [ -f "/etc/passwd" ]\r; then\r echo "exists"\r fi\r

[ -f "/etc/passwd" ]后面跟着一个回车符,测试命令的参数列表里多了一个不是合法选项的东西,于是要么报[: unexpected argument,要么干脆语法错误。更坑的是,有些版本的内置命令对尾部\r处理方式不一样,有的命令能忽略,有的直接报错,这就导致同一个脚本在不同 Linux 发行版上的表现可能天差地别,特别具有迷惑性。

2.2 三种立竿见影的换行符转换方法

知道了病因,接下来就是怎么治。我推荐三个方法,按效率排序。

方法一,dos2unix命令,一键转换。这是最直接的办法,大多数发行版默认没装,需要先安装:

# Debian/Ubuntu sudo apt-get install dos2unix # CentOS/RHEL sudo yum install dos2unix

然后转换:

dos2unix script.sh

注意它会直接修改源文件。如果你想保留原文件,可以用dos2unix -n old.sh new.sh。反向转换(Linux 转 Windows)就用unix2dos

方法二,如果你手头没有权限装软件,用sed也能做到:

sed -i 's/\r$//' script.sh

这条命令的本质是把每行结尾的\r替换成空字符串。-i表示原地修改,\r$是正则表达式,匹配“行尾的回车符”。我在生产环境上经常用这个,因为服务器不一定允许你装东西,但sed是几乎每个 Linux 系统都会有的。

方法三,纯tr命令,适合管道场景,不改源文件:

tr -d '\r' < input.sh > output.sh

tr -d是删除指定字符,'\r'就是要删掉所有回车符,然后把标准输入重定向到源文件,标准输出重定向到新文件。这个方法的好处是简单粗暴,缺点是如果你处理的是二进制文件会出问题,所以只建议针对纯文本脚本使用。

2.3 用file命令和cat -A做诊断

做运维的人最爱说一句话:先确认,再操作。转换之前你得先确认文件确实存在\r。两个命令就够了。

file命令会直接告诉你文本文件类型和换行风格:

file script.sh

如果输出里带with CRLF line terminators,说明文件是 Windows 风格。正常 Linux 脚本应该显示ASCII text或者带with LF line terminators(有些版本不显示 LF,因为 LF 是默认)。

cat -A则会把换行符显形:

cat -A script.sh

看输出:每行结尾是$表示这是\n;如果$前还有一个^M,那说明多了一个\r。我第一次给同事演示这个命令的时候,他盯着屏幕上密密麻麻的^M$愣了好几秒,然后自己默默把 VSCode 的换行符配置改了。工具只教你一种用法的话你会记住操作,但如果你能亲眼看到“看不见的字符”,从今往后你写跨平台脚本的时候会本能地留意这个细节。

3. Shebang、解释器与权限:脚本“明明没错”却执行不了的三个隐藏原因

换行符的问题解决了之后,你会发现很多脚本还是跑不起来。这时候就得把视线转向另外三个隐蔽性更强的因素。它们不会像^M那样肉眼可见,但造成的后果一模一样:脚本根本到不了执行代码那一步。

3.1 Shebang缺失或写错:内核不知道该找谁

Shebang 是脚本第一行以#!开头的声明,它告诉操作系统要用哪个解释器来执行这个文件。比如#!/bin/bash#!/usr/bin/env python3。Linux 内核在执行一个文本文件时,如果发现文件前两个字节是#!,它就会把后面的路径当作解释器,然后启动解释器并把脚本文件作为参数传给它。

如果脚本没有 Shebang,那直接执行./script.sh会怎样?这取决于你在哪个 shell 里。在 bash 里,通常会用 bash 自己来解释;但如果用户默认 shell 是 zsh 或者 sh,解析规则可能不一样,行为就可能发生变化。不过这个情况其实不算最坑的,最坑的是 Shebang 写错了或者指向了一个不存在的解释器路径。

举个例子,你在 Windows 上写脚本时用记事本建的,第一行写的是:

#! /bin/bash

注意#!/bin/bash之间多了一个空格。绝大多数情况下 bash 能容忍这种写法,但某些解释器的处理方式不一样,为了保险起见不要加空格。还有一种情况,脚本第一行写的是#!/bin/bash\r,换行符没清干净,那就回到上一节说的bad interpreter问题了。

另外一个我在实际碰到的坑:有人把脚本传到 Linux 上后,习惯性地用sh script.sh来运行,即使没有 Shebang 也可以跑。但如果脚本本身是为 bash 写的语法(数组、[[ ]]条件、source等),而系统默认的sh是 dash 的话,就会出现“在 Windows 上写着明明没问题,到 Linux 跑就一堆语法错误”的怪象。这个我们下一节详细说。

3.2 sh和bash的差异:语法没错但跑出不同结果

这是我最想让新手注意的一点:Linux 上的/bin/sh不一定是 bash。在 Debian 和 Ubuntu 上,/bin/sh是指向dash的符号链接,dash 是一个精简版的 POSIX shell,只支持 POSIX 语法的一个子集,不支持数组(至少不支持 bash 那种风格)、不支持[[ ]]、不支持source(要用.)。你在 Windows 的 Git Bash 或者 Cygwin 里写的脚本,很可能用了 bash 特有的语法,一拿到 Debian 上直接用sh xxx.sh跑,立刻报错。

如果你要确认自己的脚本需要 bash 还是 sh,第一要务是检查 Shebang。如果有#!/bin/bash,就用./script.sh跑;如果没有 Shebang,那就说明这个脚本应该遵循 POSIX 标准来写。跨平台脚本我建议全部显式声明#!/bin/bash,这样至少行为可预期。当然更严谨一点也可以只写 POSIX 语法,但如果你不是被要求必须跑在sh上,没必要给自己添这个限制。

还有个有趣的坑:你从 Windows 上用 FTP 工具(比如某些 IDE 自带的部署功能)上传脚本时,工具可能默认把换行符转换成了 Linux 风格,这反而没问题;但如果你用了scp或者直接在共享文件夹里编辑,脚本就可能是 Windows 风格。很多人困惑“是不是和编辑工具有关”,实际上和传输工具有关的情况更多。

3.3 可执行权限:chmod +x不是可选的

第三个隐藏因素,是文件权限。Windows 没有 Unix 那种“可执行位”的概念,test.bat能被运行靠的是扩展名关联,而不是文件本身带执行权限。但在 Linux 下,一个文件能不能被当成程序直接执行,取决于它有没有x权限。

你从 Windows 拷贝一个脚本到 Linux,常见的目录权限是-rw-r--r--,没有执行位。直接执行./script.sh会得到:

-bash: ./script.sh: Permission denied

解决办法很简单:

chmod +x script.sh

这个权限位单独看很简单,但它引出一个更麻烦的问题:如果你通过 FAT32 格式的 U 盘或者某些网络文件系统跨平台拷贝文件,整个文件系统的挂载选项里就可能没有执行权限支持,哪怕你chmod +x成功,下次重新挂载又回到没有权限的状态。一次我帮一个同事排查“chmod 了还是 Permission denied”,查到最后发现他的脚本放在ntfs-3g挂载的 Windows 分区上,需要改/etc/fstab的挂载选项才能解决,这是个非常容易忽略的深水区。

4. 一套完整的排查链路:从报错信息到定位根因的操作顺序

这一章我分享一下完整的实操排查链路。直接照顺序做,能省下大量时间去网上瞎搜。很多新人遇到“Permission denied”就去搜“Linux 权限”,遇到“bad interpreter”就去搜“bash 运行脚本报错”,结果查出来的答案零散且不精准。其实只要先做两个基础检查,就能把 80% 的问题划分清楚。

4.1 第一步:先用file确认脚本的真实格式

任何脚本,拷到 Linux 上之后第一件事不要着急执行,先去file一下。我自己的习惯是把它当作像仪器测温一样自然的流程步骤。

file /path/to/script.sh

这是输出样例:

script.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators

这句话直接告诉你三件事:

  • 它是一个 Bash 脚本(也有可能是 POSIX shell script)
  • 它已经是可执行文件(说明权限位可能是对的或可以加)
  • 它带 CRLF 换行符(这是当前最需要处理的问题)

如果输出是:

script.sh: Unicode text, UTF-8 (with BOM) text, with CRLF line terminators

那就更麻烦了,因为还多了一个 BOM 头的问题(下一章细说)。看到file的结果以后,你对问题的分类就有了准确判断。如果是 CRLF,按上述dos2unixsed处理转换;如果一切正常,再往下看执行方式。

4.2 第二步:按报错类型分类处理

拿到报错信息后,我习惯先做一个分类。你可以对照这个表格快速定位:

报错形态大概率原因快速处理
bad interpreter: /bin/bash^M首行 Shebang 带 CRLF转换换行符
$'\r': command not foundsyntax error near unexpected token代码行带 CRLF转换换行符
Permission denied无执行权限chmod +x
No such file or directory(但文件确实存在)Shebang 路径错误,或解释器未安装检查#!路径
command not found(针对命令)命令不存在或环境变量 PATH 不对检查命令是否安装、路径
/bin/sh: 0: Can't open script.sh用 sh 执行了不存在的文件,或路径拼错检查路径和文件名
运行后部分功能异常,但不报错命令参数差异或内置命令差异set -x追踪

有些时候file的输出已经告诉我们 CRLF 存在了,可你去挨个搜索“bad interpreter”是什么意思,绕了一大圈才明白。拿着这个表格对照,基本能一锤定音。

4.3 第三步:用set -x和shellcheck辅助排查

如果你把换行符、权限、Shebang 都排除了,脚本还是跑不出预期结果,那就得看脚本内部逻辑了。两个辅助工具非常实用。

set -x是 bash 的调试选项,它会打印每一条实际执行的命令,前面带一个+号。用法有两种:

bash -x script.sh

或者在脚本内部第二行写上:

set -x

这个选项会把变量展开之后的结果也显示出来,能帮你发现“变量值里带着一个看不见的\r”这类问题。我遇到过一次很典型的案例:脚本运行没报错,但创建出来的文件名尾都有一个问号,最后用set -x才看到变量值末尾藏着一个\r

shellcheck是另一个我必须强烈推荐的工具。它是一个静态检查工具,能直接指出脚本里的语法问题、常见陷阱和不规范写法:

# 安装 sudo apt-get install shellcheck # Debian/Ubuntu sudo yum install shellcheck # CentOS/RHEL # 检查 shellcheck script.sh

它甚至能帮你识别出部分换行符问题以及shbash混用问题。比如它会警告你在 POSIX 模式下用了 bash 特有的数组语法。对于跨平台脚本这种场景,shellcheck 的价值在于把潜在问题提前暴露,而不是等用户跑到一半才发现。

5. 不只是换行:命令差异、路径风格与编码BOM的连环坑

如果换行符和权限都处理完,脚本还是和你对着干,那你就进入了更深的领域。这一层的问题通常比较“隐性”——不会直接报错,但行为完全不对。我把踩过的坑集中说一下。

5.1 Windows命令与Linux命令不是一一对应

很多人以为在 Windows 的 cmd 或者 PowerShell 里用的命令,在 Linux 上换了终端就能直接执行。这是个天大的误会。pingipconfigfindtasklist……哪怕名字一样,参数和行为也完全不同。

举几个常见例子:

  • Windows 的find是查找文本内容的,Linux 的find是查找文件的;Windows 下查找文本用findstr,Linux 下才用grep
  • wget在 Windows 10/11 上其实也有,但行为和参数不一定一致,Linux 上的wget默认支持递归下载,Windows 那个阉割版很多选项不可用。
  • 路径分隔符:Windows 用\,Linux 用/,脚本里写死路径的话一跨就废。
  • 环境变量语法:Windows 是%VAR%(cmd)或$env:VAR(PowerShell),Linux 是$VAR

如果你的脚本里写了对 Windows 命令的调用(比如用 PowerShell 脚本的逻辑改成了 bash),要彻底审查一遍命令是否在目标 Linux 环境下存在。特别是脚本中用到的工具路径:Windows 下软件装在C:\Program Files\...,Linux 下通常在/usr/bin或者/usr/local/bin,这个差异很难用文本替换解决,需要逐个适配。

5.2 路径分隔符和盘符的隐性差异

除了命令差异,路径问题也非常隐蔽。假设脚本里有这样一行:

cd C:\Users\admin\scripts

拿到 Linux 上当然执行不了。但有些问题不是这么明显的——比如脚本是从配置文件里读路径,这个配置文件又是 Windows 软件生成的,路径分隔符就是\。在 bash 里,\是转义字符,一个单独的\在双引号里会被保留,在单引号里也会保留,但在很多场景下它会吃掉后面的字符,导致路径解析错乱。

还有盘符的问题。Linux 没有盘符的概念,所有路径都从根目录/开始。如果脚本里有C:/或者D:/这种路径,在 Linux 上会被当成相对路径处理,最终结果完全不可预期。处理这类问题的唯一办法是在脚本里避免硬编码绝对路径,改用相对路径,或者通过环境变量注入。

我记得有一次帮别人排查自动化任务,脚本在 Linux 上能跑,但是定位不到配置文件。一开始我以为是权限问题,一根set -x才发现脚本里通过$APP_HOME拼了一个\config\app.ini的后缀路径,而$APP_HOME是从 Windows 环境变量里带过来的,分隔符完全没转。所以跨平台脚本中,路径统一用/,并且尽量用/拼接目录,才是真正的“一次编写,处处运行”。

5.3 UTF-8 BOM头:一个看不见的三个字节

BOM(Byte Order Mark)是 UTF-8 编码里用来标识文件编码的标记,在文件开头写入EF BB BF三个字节。Windows 的记事本保存 UTF-8 文件时,默认会加入 BOM;而 Linux 下的很多工具不认 BOM,会把这个额外的三个字节当作真实内容来解析。

这就导致一种很邪门的情况:脚本的 Shebang 明明写着#!/bin/bash,文件也检查过换行符一切正常,但执行时报错说找不到解释器。我用xxd看过这种文件的开头:

00000000: efbb bf23 212f 6269 6e2f 6261 7368 0a ...#!/bin/bash.

看出来了吗?#!/bin/bash前面藏着efbb bf,也就是 BOM。内核看到的前两个字节不是#!,自然是找不到解释器的。

处理办法是去掉 BOM。你可以用sed

sed -i '1s/^\xEF\xBB\xBF//' script.sh

这条命令把第一行开头的 BOM 字节删掉。也可以用dos2unix,它默认就会处理 BOM。最彻底的办法还是在编辑器层面解决,后面我会专门讲怎么配置。

另外提醒一句:如果你用的是 Python 脚本,BOM 会导致 Python 解释器在读取源码时报SyntaxError: invalid character in identifier,这类问题在跨平台场景下也经常碰到。所以不仅是 shell 脚本,任何文本类脚本都有必要关注 BOM 问题。

6. 根治方案:在Windows上直接养成Linux友好的脚本编写习惯

前面讲的都是“出了问题怎么救”,但作为一个踩过无数次坑的人,我更想告诉你的是“从一开始就别让问题出现”。跨平台脚本的兼容性不是靠一次转换搞定的,而是靠整个开发和编辑链路的习惯。这一章我把自己的整套方法论写出来。

6.1 编辑器统一配置:从源头保证LF

如果你还在用 Windows 记事本写脚本,我真诚建议你立刻换掉。不是记事本不能用,而是它默认保存为 UTF-8 with BOM + CRLF,这两样都是 Linux 脚本的灾难。VSCode、Notepad++、Sublime Text 都支持自定义换行符和编码,直接把默认值改成 LF 和 UTF-8 无 BOM。

以 VSCode 为例:

  1. 左下角点击当前行尾风格,默认显示CRLF,点击后选择LF
  2. 打开设置,搜索files.eol,设为\n
  3. 搜索files.encoding,设为utf8,并且不要在设置里勾选files.autoGuessEncoding(避免不确定)。
  4. 如果你希望所有现有文件也统一转换,可以在命令面板跑Change End Of Line Sequence然后选 LF。

Notepad++ 的操作类似:菜单栏的“编辑” -> “档案格式转换” -> “转换为 UNIX 格式”,然后保存。

这里有个小细节:VSCode 的右下角行尾风格只对当前文件生效,它不会自动把所有文件都转成 LF。所以最稳妥的做法是:先打开文件,手动执行一次行尾转换,然后再在设置里把默认值改了,双管齐下。

6.2 用Git的core.autocrlf把换行符管起来

也许你已经用 Git 管理脚本了,但你知道 Git 也在悄悄干预换行符吗?Git 在 Windows 上有一个非常重要的配置项:core.autocrlf。它的作用是:

  • true时,提交到仓库时自动把 CRLF 转成 LF,检出到工作目录时自动把 LF 转成 CRLF。
  • input时,提交时转为 LF,检出时保持 LF。
  • false时,不做任何转换。

如果你在 Windows 上写脚本然后通过 Git 传到 Linux 服务器上,建议把core.autocrlf设为falseinput,同时配合.gitattributes文件来精细化控制。我个人的做法是在仓库根目录放一个.gitattributes

* text=auto eol=lf *.sh text eol=lf *.py text eol=lf

这样不管谁在什么系统上提交,只要他和这个仓库打交道,换行符在入库和检出时都会被强制成 LF。这个方案能从根本上避免团队协作时的换行符混乱。

不过要注意,.gitattributes只对之后的操作生效,仓库里已有的文件还是要手动转换一次,否则 Git 可能认为文件没有变化。你需要做一次“重新规范化”操作,大致流程是把文件从索引中移除、重新添加,让 Git 按照新的属性重新规范化内容。这个操作网上有很多资料,属于 Git 的高级用法,但一次配置终身受益。

6.3 有条件就上WSL:让开发和运行环境一致

如果你长期做跨平台开发或者运维脚本编写,我强烈建议你在 Windows 上直接启用 WSL(Windows Subsystem for Linux),在 WSL 里写脚本、跑脚本、再部署到远程 Linux 服务器。这不是绕远路,而是从根上消灭“环境差异”的问题。

WSL 里运行的是真正的 Linux 内核(WSL2 是轻量级虚拟机),你写的 bash 脚本在 WSL 里跑和在服务器上跑的行为基本一致。更关键的是,你在 WSL 里创建的文件默认就是 LF 换行、无 BOM,文件权限也会被正确保留。这样一来,Windows 和 Linux 之间的脚本兼容性问题根本不会产生。

我的建议工作流是:

  • Windows 上用 VSCode 写代码,用 Remote-WSL 插件连接到 WSL 环境;
  • 写完后直接在 WSL 里用 bash 跑一遍测试;
  • 确认没问题了,再通过 Git 或者 scp 部署到远程服务器。

听起来多了一层,实际上省掉的是大量排障时间。尤其是你如果经常要写部署脚本、定时任务脚本,WSL 这套工作流用起来非常顺手。

6.4 一套我常用的跨平台脚本开发检查清单

最后分享一份我打印出来贴在工位上的检查清单。每次写完跨平台脚本,或者从 Windows 拷贝脚本到 Linux 之前,按这个顺序过一遍:

  1. 确认编辑器默认保存为 LF 换行、UTF-8 无 BOM。
  2. 确认 Git 仓库里设置了core.autocrlf false.gitattributes强制 LF。
  3. 确认脚本第一行 Shebang 是#!/bin/bash#!/usr/bin/env bash,没有多余空格。
  4. dos2unix或者sed -i 's/\r$//'显式预处理一次。
  5. 上传后先执行file script.sh,确认没有 CRLF、没有 BOM、脚本类型正确。
  6. 执行chmod +x script.sh赋予执行权限。
  7. 如果怀疑权限,用ls -l script.sh看权限位。
  8. 小规模执行,配合bash -x观察变量展开是否符合预期。
  9. 静态检查能跑的话跑一下shellcheck script.sh
  10. 涉及路径的地方,统一使用/,使用相对路径或环境变量,避免硬编码 Windows 盘符。

这一套流程看着繁琐,但实际执行下来一分钟都用不到。别嫌多,等你哪次部署到生产环境被一个\r搞得满头大汗,你就知道这一分钟有多值钱了。

我个人在实际操作中的体会是:跨平台脚本问题,技术难度其实很低,难的是你愿不愿意在每个环节多留一个心眼。换行符、编码、权限、解释器,每一个单独拿出来都简单到不值一提,但它们组合在一起,就能把一段逻辑完全正确的代码变成一个让人抓狂的谜题。希望这篇内容能帮你把这条路上的坑提前填平。下次再遇到“Windows 下编写的脚本无法在 Linux 中运行”,别急着怀疑语法,先按这套流程走一遍,多半能快速解决问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询