如何判断当前运行的是未编译.ts脚本还是编译后的Deno可执行文件?
在Deno中区分编译可执行文件与脚本运行模式的最优方案
我需要为程序创建指向自身的符号链接:开发阶段以脚本运行时,符号链接目标用Deno.mainModule;编译为可执行文件分发时,目标用Deno.execPath()。核心问题是如何准确判断当前运行的是编译后的二进制文件还是脚本模式。
现有启发式方法的局限性
你提到的两种方法都存在不稳定的情况:
- 主模块路径匹配法:
Deno.mainModule === path.toFileUrl(Deno.execPath()) + '.ts'- 失效场景:编译后的可执行文件与源文件不在同一目录、源文件使用
.js等非.ts后缀、Windows路径编码差异。
- 失效场景:编译后的可执行文件与源文件不在同一目录、源文件使用
- 执行文件名判断法:
path.basename(Deno.execPath()) !== 'deno'- 失效场景:用户将编译后的可执行文件命名为
deno、系统中存在其他同名可执行文件。
- 失效场景:用户将编译后的可执行文件命名为
最优实践:官方API优先+兼容 fallback
Deno 1.28及以上版本提供了Deno.runner API,可直接获取运行时的执行器类型,这是最可靠的判断方式。对于旧版本,可结合两种启发式方法降低误判率:
import * as path from "https://deno.land/std/path/mod.ts"; // 判断是否为编译后的可执行文件 const isCompiledBinary = (): boolean => { // 优先使用官方API(Deno 1.28+) if (typeof Deno.runner !== "undefined") { return Deno.runner.kind === "binary"; } // 旧版本兼容方案:组合两种启发式判断 const execFilename = path.basename(Deno.execPath(), ".exe"); const isNotDenoExec = execFilename !== "deno"; const execPathWithSourceExt = path.toFileUrl(Deno.execPath()).href + ".ts"; const isSourceMatchesExec = Deno.mainModule === execPathWithSourceExt; return isNotDenoExec || isSourceMatchesExec; }; // 获取符号链接的目标路径 const getSymlinkTarget = (): string => { return isCompiledBinary() ? Deno.execPath() : path.fromFileUrl(Deno.mainModule); };
方案说明
- 官方API判断:
Deno.runner.kind在编译二进制中返回"binary",脚本运行时返回"cli",完全避免启发式方法的误判。 - 兼容逻辑:旧版本中通过“执行文件名非deno”或“源文件路径与执行文件路径匹配”的逻辑或,大幅降低单一方法的失效概率。
- Windows适配:用
path.basename的第二个参数自动去除.exe后缀,兼容Windows平台。
注意事项
- 若你的源文件使用
.js等其他后缀,需修改execPathWithSourceExt中的后缀部分。 - 建议升级到Deno 1.28+版本,直接使用
Deno.runner的权威判断。
内容的提问来源于stack exchange,提问作者Stabby
相关产品推荐
相关产品推荐

