执行shell脚本出现 $‘ \r‘ 符号导致执行失败【解决】

👨‍🎓博主简介

  🏅CSDN博客专家
  🏅云计算领域优质创作者
  🏅华为云开发者社区专家博主
  🏅阿里云开发者社区专家博主
💊交流社区:运维交流社区 欢迎大家的加入!
🐋 希望大家多多支持,我们一起进步!😄
🎉如果文章对你有帮助的话,欢迎 点赞 👍🏻 评论 💬 收藏 ⭐️ 加关注+💗


问题

  在执行脚本的时候,我们有时候会遇到添加一个变量值,明明读到的值是0或者1,在外面执行此命令都是没问题的,而且脚本中写的判断也是没问题的,但是为什么执行的结果是没有找到0或者1呢?

问题的排查及原因

  • 脚本示例(test.sh):
#!/bin/bash

#获取脚本执行的路径
DIR=$(cd $(dirname $0) && pwd )

num=$(cat $DIR/peizhi.properties | egrep "^onenumber" | awk -F "=" '{print $2}')

if [ "$num" == 0 ];then
        echo -e "配置文件中\e[1;34m测试服务\e[0m\e[1;32m已打开\e[0m"
else
        echo -e "配置文件中\e[1;31m测试服务没有打开\e[0m,跳过此判断"
fi
  • 配置文件示例(peizhi.properties):
file=1.txt
onenumber=0
format=json

1、我们先分析脚本:

查看当前目录下的peizhi.properties配置文件中的以onenumber开头的文件;

= 后面的值,如果为0,那么就输入已经打开这个配置了;如果不等于0那么就输出没有打开这个配置。

2、然后我们先在linux命令行执行此命令: cat peizhi.properties | egrep "^onenumber" | awk -F "=" '{print $2}',查到的结果为:0,那么我们应该输出“配置文件中测试服务已打开”

3、放到脚本里执行:发现直接结果是:“配置文件中测试服务没有打开,跳过此判断”

image-20240506131109078

4、打开配置文件和脚本看看文件的格式,是不是都是unix的;vim 打开配置文件和脚本,执行::set ff,查看此脚本或者文件的文件格式;

image-20240506132210216

image-20240506132225669

可以看到,脚本是没问题的,是unix格式的;但是配置文件就是dos格式的了;dos格式为windows(CR LF),在windows上编写的shell脚本,在Linux系统中运行就会有\r ^M等错误信息;

所以,两个脚本文件格式都必须为unix格式,查看脚本是否为unix格式,vim进入脚本编辑器,执行::set ff查看脚本的文件格式;如果是dos的就是windows格式的,如果是unix就是linux格式的;dos格式的在windows回车是有一个隐藏的内容的\r,所以在执行脚本的时候会多出现一个\r

5、然后我们再去看一下,执行脚本的过程;sh -x test.sh

发现多了一个\r,然后导致下面的判断识别成了0\r0不匹配了,所以输出了没有打开此测试服务;

image-20240506141334744


所以,得出的结论是:因为两个文件中的 配置文件的文件格式为dos格式,dos为windows模式,回车会有\r占位符,所以,导致执行shell脚本的时候多了一个\r

两种解决方法:

  • 1、修改文件的文件格式
  • 2、去除文件中的回车:\r

解决方法一:修改文件 文件格式

当我们知道是配置文件的文件类型是dos类型,那么我们就可以只修改配置文件的文件类型即可;

  • 修改文件 文件格式

1、vim 进入编辑模式

2、执行: set ff=unix

3、:wq保存退出

4、再次进入查看文件格式::set ff

image-20240506151715360

image-20240506151812879

5、执行脚本带详细输出

root@7b64cee30106:~# sh -x test.sh 
+++ dirname test.sh
++ cd .
++ pwd
+ DIR=/root
++ cat /root/peizhi.properties
++ grep '^onenumber'
++ awk -F = '{print $2}'
+ num=0
+ '[' 0 == 0 ']'
+ echo -e '配置文件中\e[1;34m测试服务\e[0m\e[1;32m已打开\e[0m'
配置文件中测试服务已打开

可以发现已经是 0 = 0 了,那么问题就解决了;

image-20240506151925543

解决方法二:去除文件类型为“dos”文件中的回车

当我们知道是配置文件的文件类型是dos类型,那么我们就只去除配置文件里的\r就行;

  • 去除文件类型为“dos”文件中的回车\r
sed -i "s/\r//g" peizhi.properties

命令解析:

sed -i:		修改配置文件 
"s/\r//g":	将\r改为空格,文件中所有
peizhi.properties	要修改的文件名
  • 执行脚本带详细输出
root@7b64cee30106:~# sh -x test.sh 
+++ dirname test.sh
++ cd .
++ pwd
+ DIR=/root
++ cat /root/peizhi.properties
++ grep '^onenumber'
++ awk -F = '{print $2}'
+ num=0
+ '[' 0 == 0 ']'
+ echo -e '配置文件中\e[1;34m测试服务\e[0m\e[1;32m已打开\e[0m'
配置文件中测试服务已打开

可以发现已经是 0 = 0 了,那么问题就解决了;

image-20240506151925543



小知识:

  在windows上使用notepad++可以看到该文件的文件类型是什么;打开一个文件或者脚本在右下角可以看到。

image-20240506154549293

<think>我们正在解决执行Shell脚本时提示第一行`#!/bin/sh`不存在的问题。 根据用户描述,错误提示是"没有找到文件或目录",这通常意味着系统找不到shebang行指定的解释器。 参考引用内容: 引用[1]和[2]解释了shebang行的作用:它指定了执行脚本的解释器路径。 引用[4]提到,在Linux系统中,`/bin/sh`通常是一个符号链接,可能指向不同的shell(如bash或dash)。 可能的原因及解决方案: 1. **/bin/sh 解释器不存在或路径错误**: 在系统中,`/bin/sh`可能不存在,或者它是一个损坏的符号链接。 我们可以检查`/bin/sh`是否存在: ls -l /bin/sh 如果不存在,我们需要安装一个兼容的shell。通常,`dash`或`bash`会提供`sh`。 在Debian/Ubuntu系统中,可以安装dash: sudo apt-get install dash 在CentOS/RHEL系统中,可以安装bash(通常已经安装,但可能没有链接到/bin/sh): sudo yum install bash 然后,确保`/bin/sh`指向一个有效的解释器。通常,我们可以通过重新建立符号链接来解决: sudo ln -sf /bin/bash /bin/sh # 或者使用 /bin/dash 注意:改变`/bin/sh`的指向可能会影响系统脚本,因为很多系统脚本使用`#!/bin/sh`。所以建议在用户脚本中直接使用`#!/bin/bash`,以避免依赖系统默认的sh。 2. **脚本本身格式问题(如DOS换行符)**: 虽然用户提到的是第一行解释器路径找不到,但有时候由于脚本文件包含DOS换行符(CRLF),导致解释器路径被识别为`/bin/sh\r`(注意末尾的\r),系统当然找不到这个文件。 我们可以使用`dos2unix`工具转换: dos2unix your_script.sh 或者使用sed命令: sed -i 's/\r$//' your_script.sh 3. **脚本解释器路径错误**: 如果系统中`sh`的路径不是`/bin/sh`,我们可以通过以下命令查找`sh`的位置: which sh 然后修改脚本shebang行为正确的路径,例如: #!/usr/bin/sh 或者,如果找到了sh在`/usr/bin/sh`,则修改脚本第一行为`#!/usr/bin/sh`。 4. **文件系统挂载问题**: 如果`/bin`目录被挂载到其他位置,或者因为某些原因不可访问,我们需要检查文件系统。 5. **使用绝对路径执行脚本**: 确保执行脚本时使用正确的路径,比如: ./script.sh # 当前目录下的script.sh 或者使用绝对路径。 操作步骤: 步骤1:检查/bin/sh是否存在 ls -l /bin/sh 步骤2:如果不存在,安装sh(通常通过安装bash或dash)并创建符号链接(谨慎操作,特别是生产环境) 步骤3:如果存在,检查它是否是一个有效的可执行文件。可以尝试直接运行: /bin/sh -c "echo hello" 步骤4:检查脚本的格式,转换换行符(如果脚本是从Windows复制过来的) 步骤5:如果/bin/sh存在且有效,那么可能是脚本本身的权限问题。确保脚本执行权限: chmod +x your_script.sh 步骤6:如果以上都不行,尝试修改脚本shebang行为其他解释器,比如`#!/bin/bash`(假设bash已安装且路径正确)。 注意:在修改系统默认的`/bin/sh`链接时要谨慎,因为系统脚本可能依赖于特定的sh(如dash或bash的POSIX模式)。对于用户自己的脚本,建议明确使用`#!/bin/bash`或`#!/usr/bin/env bash`。 如果用户不想修改系统默认的sh,可以在自己的脚本中直接使用`#!/bin/bash`(前提是bash已安装)。 示例操作: 假设我们的脚本名为`test.sh`,第一行是`#!/bin/sh`,执行时出现错误。 1. 转换脚本格式: dos2unix test.sh 2. 添加执行权限: chmod +x test.sh 3. 检查/bin/sh$ ls -l /bin/sh lrwxrwxrwx 1 root root 4 Mar 18 2020 /bin/sh -> dash 如果输出类似这样,说明符号链接存在。 4. 如果/bin/sh不存在,我们可以创建指向bash的链接(如果bash在/bin/bash): sudo ln -s /bin/bash /bin/sh 或者安装dash并链接(在Debian/Ubuntu上): sudo apt-get install dash sudo ln -s /bin/dash /bin/sh 5. 如果不想修改系统链接,直接修改脚本第一行为`#!/bin/bash`(如果bash存在): sed -i '1s|#!/bin/sh|#!/bin/bash|' test.sh 6. 如果/bin/sh存在但执行脚本仍然报错,尝试直接运行解释器: /bin/sh test.sh # 这样会忽略脚本自身的shebang,而使用命令行指定的解释器 如果直接运行成功,说明问题可能出在脚本shebang行格式(如不可见的字符)或者文件系统问题。 流程图: ```mermaid graph TD A[执行脚本报错“没有文件或目录”] --> B{检查/bin/sh是否存在} B -->|存在| C[检查脚本格式:dos2unix] B -->|不存在| D[安装sh(bash或dash)并创建链接] C --> E[修改脚本权限:chmod +x] E --> F[再次执行] F -->|成功| G[结束] F -->|失败| H[检查/bin/sh是否有效:运行/bin/sh -c 'echo hello'] H -->|无效| I[修复/bin/sh链接] H -->|有效| J[检查脚本首行是否有不可见字符] J --> K[使用sed或编辑器修复首行] D --> E ``` 相关问题: 1. 如何安全地修改系统默认的/bin/sh符号链接? 2. Shell脚本shebang行的最佳实践是什么? 3. 如何检测和修复脚本文件中的DOS换行符? 4. 在Linux系统中,如何安装和配置不同的Shell解释器?</think>执行 Shell 脚本时提示 `#! /bin/sh 没有找到文件或目录` 错误,通常由以下原因导致。请按顺序排查: --- ### 一、核心原因解决方案 #### 1. **解释器路径错误(最常见)** - **系统缺少 `/bin/sh` 解释器** 通过命令检查 `/bin/sh` 是否存在: ```bash ls -l /bin/sh # 查看文件状态 file /bin/sh # 验证文件类型 ``` - 若输出 `No such file or directory`,说明系统未安装基础 Shell 解释器 - **修复方法**:安装 POSIX 兼容的 Shell(如 `dash` 或 `bash`) ```bash # Debian/Ubuntu sudo apt-get install dash # CentOS/RHEL sudo yum install bash ``` #### 2. **符号链接损坏** - `/bin/sh` 通常是符号链接(如指向 `/bin/dash` 或 `/bin/bash`) 检查链接目标是否有效: ```bash ls -l /bin/sh # 正常应显示类似 lrwxrwxrwx ... /bin/sh -> dash ``` - **修复方法**:重建符号链接 ```bash sudo ln -sf /bin/bash /bin/sh # 指向 bash(推荐) # 或 sudo ln -sf /bin/dash /bin/sh # 指向 dash ``` #### 3. **脚本文件格式问题(Windows 换行符)** - Windows 编辑的脚本包含 `\r` 回车符,导致路径被识别为 `/bin/sh\r` **修复方法**: ```bash # 安装转换工具 sudo apt install dos2unix # Debian/Ubuntu sudo yum install dos2unix # CentOS/RHEL # 转换脚本格式 dos2unix your_script.sh ``` *或使用 sed*: ```bash sed -i 's/\r$//' your_script.sh # 删除回车符 ``` #### 4. **文件权限问题** - 脚本或解释器缺乏执行权限: ```bash # 添加脚本执行权限 chmod +x your_script.sh # 验证解释器权限 ls -l /bin/sh # 应显示 -rwxr-xr-x 或类似 ``` --- ### 二、高级排查步骤 #### 1. **验证解释器路径** - 查找替代的 `sh` 路径: ```bash which sh # 通常为 /bin/sh 或 /usr/bin/sh command -v sh ``` - 修改脚本shebang 行: ```bash # 将 #!/bin/sh 改为实际路径(如 /usr/bin/sh) sed -i '1s|#!/bin/sh|#!/usr/bin/sh|' your_script.sh ``` #### 2. **绕过 shebang 直接执行** ```bash /bin/bash your_script.sh # 强制用 bash 执行 /bin/dash your_script.sh # 强制用 dash 执行 ``` #### 3. **检查文件系统错误** ```bash # 查看 /bin 分区状态 df -h /bin # 检测磁盘错误 sudo fsck /dev/sda1 # 替换为实际分区 ``` --- ### 三、操作流程图 ```mermaid graph TD A[报错“#!/bin/sh 未找到”] --> B{检查 /bin/sh 是否存在} B -->|存在| C[验证符号链接目标] B -->|不存在| D[安装 dash 或 bash] C -->|链接损坏| E[重建符号链接] C -->|链接正常| F[检查脚本格式] D --> G[创建 /bin/sh 链接] F -->|含 \\r 回车符| H[dos2unix 转换] F -->|格式正常| I[检查文件权限] H --> I I -->|无执行权| J[chmod +x 脚本] I -->|权限正常| K[测试 /bin/sh -c 'echo test'] K -->|失败| L[修复解释器安装] K -->|成功| M[执行成功] ``` > **关键提示**: > 1. 优先使用 `#!/bin/bash` 替代 `#!/bin/sh` 避免兼容性问题[^1][^4] > 2. 通过 `cat -v your_script.sh | head -1` 检查 shebang 行是否含 `^M`(回车符) > 3. 99% 的案例通过 **重建 /bin/sh 链接** 或 **转换脚本格式** 解决 ---
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A-刘晨阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值