资讯详情

资讯详情

Linux执行.sh文件提示No such file or directory?TaoToken场景下的排查与解决方法

1. 脚本明明就在眼前为什么 Linux 说 No such file or directory你大概率遇到过这个画面ls -l deploy.sh明明能看到文件./deploy.sh一敲回车终端却回你一句bash: ./deploy.sh: No such file or directory。第一反应是文件被删了再ls一遍它还在。于是开始怀疑人生。这个报错在 Linux 下运行 .sh 脚本时非常典型它的迷惑点在于报错说的「文件不存在」往往不是脚本本身不存在而是脚本依赖的某个东西不存在。最常见的就是 shebang 那一行#!/bin/bash里的解释器路径对不上或者文件里混进了 Windows 的\r回车符导致内核把#!/bin/bash\r当成一个根本不存在的解释器去查找。我把它拆成几类根因你可以对照自己的场景快速定位第一类是换行符问题。在 Windows 编辑器里写的脚本行尾是\r\n传到 Linux 后 shebang 变成#!/bin/bash\r。内核解析 shebang 时会把\r也算进解释器路径于是去找一个叫/bin/bash\r的程序当然找不到报错就落到脚本名上。第二类是解释器路径问题。比如脚本写的是#!/usr/bin/env python3但目标机器上没装 python3或者路径是/usr/local/bin/bash而实际 bash 在/bin/bash。shebang 指向的可执行文件不存在同样报这个错。第三类是文件编码问题。UTF-8 BOM 头EF BB BF会让 shebang 前面多出不可见字节内核识别不了#!也会失败。第四类是权限与挂载问题。脚本没有执行权限时通常报Permission denied但如果挂载点带了noexec选项或者你在容器里跑、宿主机文件通过 volume 挂进来表现就可能变成找不到文件。第五类是路径与工作目录问题。./deploy.sh里的./依赖当前目录如果你cd到了别处或者脚本内部引用了相对路径的资源文件也会触发类似报错。这篇就按「先确认现象、再逐层排查、最后修复验证」的顺序走一遍。我会给出可以直接复制的file、od、sed、chmod、bash -x命令也会顺带说下在 TaoToken 这类需要跑自动化脚本、做模型调用和 Agent 编排的场景里怎么把脚本环境一次性弄干净避免每次部署都踩同一个坑。适合刚接触 Linux 的同学也适合天天写 CI/CD、被脚本坑过的老手。2. 排查前的环境准备与 TaoToken 场景说明在动手改脚本之前先把「观察工具」备齐。Linux 自带的那几个命令就够用不需要额外装东西。我习惯按这个顺序看一遍# 1. 确认文件确实存在并看到它的权限、大小、时间 ls -l deploy.sh # 2. 看文件类型和编码线索file 会告诉你是不是带 CRLF file deploy.sh # 3. 直接看 shebang 那一行的原始字节\r 会显示成 \r head -1 deploy.sh | od -c # 4. 看文件格式dos/unixvim 里也能看 cat -A deploy.sh | head -3file命令的输出很关键。如果它显示with CRLF line terminators那基本就是换行符问题如果显示UTF-8 Unicode (with BOM)那就是 BOM 头问题。od -c会把每个字节摊开给你看\r和\n一目了然。为什么要在 TaoToken 场景下特别强调这套排查因为很多做 AI 应用的朋友工作流是这样的本地 Windows 或 macOS 上写好调用脚本通过 Git 推到服务器服务器上跑定时任务去请求模型接口、处理数据、生成报告。脚本一旦因为换行符或 shebang 挂掉整个自动化链路就断了而且报错信息还特别误导人容易往「网络问题」「API 挂了」的方向去查白白浪费时间。TaoToken 提供的是兼容主流协议的大模型 API 接入能力官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。你可以用 curl、Python、Node 等任意方式去调用。实际项目里我通常会把调用逻辑封装成一个.sh脚本配合环境变量管理 Key然后交给 cron 或 CI 去执行。这时候脚本本身的健壮性就很重要了——shebang 要写对、换行符要统一、权限要给足否则你会在「脚本跑不起来」和「API 调不通」之间反复横跳。所以这一节的目标很简单先把排查工具和思路建立起来知道每一步在看什么。下一节开始给可复制的配置和修复命令。3. 可复制的修复配置换行符、shebang、权限一次改对这一节是全文的核心我给的都是能直接粘贴执行的命令。建议你先备份原文件再动手cp deploy.sh deploy.sh.bak3.1 换行符从 CRLF 改成 LF这是最高频的根因。三种改法按场景选方法一用sed原地删除\r最通用sed -i s/\r$// deploy.sh方法二用dos2unix工具如果系统装了它dos2unix deploy.sh方法三在 vim 里改适合你想顺便检查内容vim deploy.sh # 进入后输入 :set ff # 如果显示 fileformatdos改成 :set ffunix # 保存退出 :wq改完再用file deploy.sh确认输出里不应该再有CRLF字样。3.2 shebang 写对别让解释器路径坑你先确认目标解释器的真实路径which bash which sh which python3然后按结果改脚本第一行。推荐用env方式兼容性最好#!/usr/bin/env bash如果你确定环境里 bash 就在/bin/bash直接写绝对路径也行#!/bin/bash注意shebang 必须是文件的第一行第一个字符前面不能有空行、空格或 BOM。如果你用sed改 shebang可以这样sed -i 1s|^.*$|#!/usr/bin/env bash| deploy.sh3.3 去掉 UTF-8 BOM 头如果file提示有 BOM用这条命令去掉sed -i 1s/^\xEF\xBB\xBF// deploy.sh3.4 给足执行权限chmod ux deploy.sh # 或者更明确 chmod 755 deploy.sh确认权限ls -l deploy.sh # 应该看到 -rwxr-xr-x 之类x 位存在3.5 一个可直接复用的 settings 片段在 TaoToken 相关的自动化项目里我习惯把环境变量和脚本配置分离。下面是一个.env风格的配置片段配合脚本读取避免把 Key 硬编码进.sh# .env 文件不要提交到 Git TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的key TAOTOKEN_MODEL你的模型ID脚本里这样读#!/usr/bin/env bash set -euo pipefail # 加载环境变量 if [ -f .env ]; then export $(grep -v ^# .env | xargs) fi # 校验必要变量 : ${TAOTOKEN_BASE_URL:?缺少 TAOTOKEN_BASE_URL} : ${TAOTOKEN_API_KEY:?缺少 TAOTOKEN_API_KEY} : ${TAOTOKEN_MODEL:?缺少 TAOTOKEN_MODEL} echo 配置加载完成准备调用模型这里set -euo pipefail很关键-e让命令失败即退出-u让未定义变量报错-o pipefail让管道中任一环节失败都能被捕获。很多脚本「静默失败」就是缺了这几行。如果你用的是 JSON 配置比如某些 Agent 框架可以这样组织{ base_url: https://taotoken.net/api, api_key: sk-你的key, model: 你的模型ID, timeout: 60 }注意 Base URL、API Key、Model ID 这三件套要配套出现缺一个调用就会失败。Key 的获取入口在控制台的 API Keys 页面文档在接入文档里具体链接我在最后一节统一给。4. 验证脚本能跑从 bash -x 到真实请求成功改完配置别急着上生产先本地验证。这一节给你一套从「语法检查」到「真实调用成功」的完整验证流程。4.1 语法检查bash -n deploy.sh-n只做语法解析不执行能提前发现括号不匹配、关键字拼错等问题。没输出就是通过。4.2 单步调试bash -x deploy.sh-x会打印每一条实际执行的命令前面带号。如果脚本中途挂了你能立刻看到是卡在哪一行。这是排查「脚本跑一半没反应」的利器。4.3 确认 shebang 生效./deploy.sh如果这一步还报No such file or directory回到第 3 节重新检查换行符和 shebang。如果报Permission denied检查chmod。4.4 真实请求验证假设你的脚本是调用模型接口可以用 curl 先单独验证连通性curl -sS -X POST ${TAOTOKEN_BASE_URL}/v1/chat/completions \ -H Authorization: Bearer ${TAOTOKEN_API_KEY} \ -H Content-Type: application/json \ -d { \model\: \${TAOTOKEN_MODEL}\, \messages\: [{\role\: \user\, \content\: \你好请回复一句话\}] }成功的话你会拿到一段 JSON里面有choices字段和模型返回的内容。如果这里就失败那问题不在脚本而在网络或 Key 配置可以对照下一节的报错表排查。4.5 把验证写进脚本我习惯在脚本开头加一段自检跑之前先确认环境#!/usr/bin/env bash set -euo pipefail echo [1/3] 检查依赖命令 for cmd in curl jq; do command -v $cmd /dev/null 21 || { echo 缺少命令: $cmd; exit 1; } done echo [2/3] 检查环境变量 : ${TAOTOKEN_BASE_URL:?} : ${TAOTOKEN_API_KEY:?} : ${TAOTOKEN_MODEL:?} echo [3/3] 发起测试请求 resp$(curl -sS -X POST ${TAOTOKEN_BASE_URL}/v1/chat/completions \ -H Authorization: Bearer ${TAOTOKEN_API_KEY} \ -H Content-Type: application/json \ -d {\model\:\${TAOTOKEN_MODEL}\,\messages\:[{\role\:\user\,\content\:\ping\}]}) echo $resp | jq -r .choices[0].message.content // 无返回内容这段脚本跑通说明你的 .sh 执行环境、换行符、权限、API 配置全部正常。之后接进 cron 或 CI 就稳了。5. 常见报错对照排查401、local proxy failed、reading choices、OAuth脚本能执行了不代表调用就成功。下面这张表是我实际踩过的坑按报错信息对照着查。报错信息可能原因排查动作401 UnauthorizedAPI Key 错误、过期或没带上检查Authorization: Bearer头确认 Key 从控制台复制完整local proxy failed本地网络或代理配置干扰检查http_proxy/https_proxy环境变量必要时 unsetreading choices相关解析错误返回体不是预期 JSON或模型名不对先打印原始响应确认model字段与可用模型一致OAuth相关失败认证方式与接口不匹配确认用的是 API Key 方式而非 OAuth 流程No such file or directory换行符/shebang/权限回到第 3 节用file和od -c确认Permission denied缺执行权限chmod uxbad interpretershebang 路径错which bash后改 shebang重点说几个容易误判的401 不一定是 Key 错。有时候是脚本里变量没加载成功${TAOTOKEN_API_KEY}展开成空字符串请求头变成Bearer服务端自然拒绝。用set -u能让这种情况直接报错退出而不是静默发一个空 Key 的请求。local proxy failed 要查环境变量。很多开发机配了全局代理脚本跑起来会继承这些变量。可以这样确认env | grep -i proxy如果确实有临时清掉再跑unset http_proxy https_proxy all_proxyreading choices 报错通常是响应结构问题。可能是模型名写错服务端返回了错误 JSON而你的脚本还在按成功结构去取choices[0]。养成先打印原始响应的习惯echo $resp | jq .jq .会格式化输出结构对不对一眼就能看出来。OAuth 失败说明你用的认证方式和接口要求不匹配。TaoToken 的 API 走的是 API Key 方式在请求头里带Authorization: Bearer不需要走 OAuth 授权码流程。如果你从别的地方抄了一段 OAuth 代码记得换掉。排查时还有一个通用技巧把bash -x和curl -v结合用。-v会打印完整的请求头和响应头能看清到底发出去了什么。curl -v -X POST ${TAOTOKEN_BASE_URL}/v1/chat/completions \ -H Authorization: Bearer ${TAOTOKEN_API_KEY} \ -H Content-Type: application/json \ -d {\model\:\${TAOTOKEN_MODEL}\,\messages\:[{\role\:\user\,\content\:\test\}]}看到 Authorization: Bearer sk-xxx说明头带对了看到 HTTP/1.1 200 OK说明服务端接受了。6. 把脚本环境固化下来长期编码与 Agent 场景的接入建议单次修好一个脚本不难难的是团队里每个人、每台机器都不再踩同一个坑。这一节说几个我实践下来有效的做法。第一在仓库里加.gitattributes强制 shell 脚本用 LF*.sh text eollf这样无论谁在 Windows 上 cloneGit 都会自动把换行符转成 LF从源头杜绝 CRLF 问题。第二在 CI 里加一道检查。比如 GitHub Actions 里跑- name: Check shell scripts run: | find . -name *.sh -exec bash -n {} \; find . -name *.sh -exec file {} \; | grep -q CRLF exit 1 || true语法不过或带 CRLF 直接让流水线失败比上线后才发现强得多。第三统一用#!/usr/bin/env bash并在脚本开头加set -euo pipefail。这两条能挡掉大量低级错误。第四Key 和配置走环境变量或密钥管理不要硬编码。TaoToken 的 Key 在控制台的 API Keys 页面管理接入细节看接入文档。如果你要做长期的编码任务、Agent 编排、批量调用可以考虑 Coding Plan它更适合持续性的开发场景比按次调用更省心。具体入口我整理在这里按需取用想先体验模型对话效果模型对话需要管理 KeyAPI Keys看接入文档接入文档长期编码 / Agent 场景Coding Plan控制台总入口控制台最后说个我自己的习惯每个新项目初始化时先写一个check_env.sh把依赖命令、环境变量、网络连通性全检查一遍跑通再写业务逻辑。这个脚本本身也用#!/usr/bin/env bash和 LF 换行作为模板复制到各个项目。这样无论换机器还是换同事环境问题都能在五分钟内定位而不是花半天在「文件明明在却说不存在」上打转。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →