require를 통해 호출되는지 아니면 명령줄을 통해 직접 호출되는지 탐지
내 노드의 여부를 탐지하려면 어떻게 해야 합니까?SH를 사용하여 JS 파일을 호출했습니다.node path-to-file
또는 JS:require('path-to-file')
?
노드입니다.이전 Perl 질문과 동일한 JS: require가 로드되지 않은 경우에만 Perl 스크립트를 실행하려면 어떻게 해야 합니까?
if (require.main === module) {
console.log('called directly');
} else {
console.log('required as a module');
}
이에 대한 설명서는 https://nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module 에서 참조하십시오.
조금 더 짧은 또 다른 방법이 있습니다(위에서 언급한 문서에는 설명되어 있지 않음).
var runningAsScript = !module.parent;
저는 이 블로그 게시물에서 이 모든 것이 어떻게 작동하는지에 대해 더 자세히 설명했습니다.
ES Module(및 Node 10.12+)을 사용하는 경우 다음을 사용할 수 있습니다.import.meta.url
:
import path from 'path';
import { fileURLToPath } from 'url'
const nodePath = path.resolve(process.argv[1]);
const modulePath = path.resolve(fileURLToPath(import.meta.url))
const isRunningDirectlyViaCLI = nodePath === modulePath
같은 것들require.main
,module.parent
그리고.__dirname
/__filename
ESM에서는 사용할 수 없습니다.
참고: ESLint를 사용하는 경우 이 구문이 질식할 수 있습니다. 이 경우 ESLint로 업데이트하고 다음을 수행해야 합니다.
ecmaVersion
까지11
(2020
).
추가 정보: ,
저는 설명에 사용된 용어 때문에 약간 혼란스러웠습니다.그래서 저는 몇 가지 간단한 테스트를 해야 했습니다.
다음과 같은 결과가 나온다는 것을 알게 되었습니다.
var isCLI = !module.parent;
var isCLI = require.main === module;
그리고 다른 혼란스러운 사람들을 위해 (그리고 질문에 직접 대답하기 위해):
var isCLI = require.main === module;
var wasRequired = !isCLI;
ES6 모듈을 사용하는 경우 다음을 시도합니다.
if (process.mainModule.filename === __filename) {
console.log('running as main module')
}
저는 항상 이 빌어먹을 코드 조각을 쓰는 방법을 기억하려고 노력하는 제 자신을 발견합니다. 그래서 저는 그것을 위한 간단한 모듈을 만들기로 결정했습니다.호출자의 모듈 정보에 접근하는 것이 간단하지 않기 때문에 작동하는 데 시간이 좀 걸렸지만, 어떻게 할 수 있는지 보는 것은 재미있었습니다.
그래서 아이디어는 모듈을 호출하여 발신자 모듈이 메인 모듈인지 묻는 것입니다.우리는 발신자 기능의 모듈을 파악해야 합니다.저의 첫 번째 접근 방식은 수용된 답변의 변형이었습니다.
module.exports = function () {
return require.main === module.parent;
};
하지만 그것이 효과가 있다는 것은 보장되지 않습니다. module.parent
호출하는 모듈이 아니라 메모리에 로드된 모듈을 가리킵니다.호출자 모듈이 이 도우미 모듈을 메모리에 로드한 것이라면 문제 없습니다.하지만 그렇지 않다면, 작동하지 않을 것입니다.그래서 우리는 다른 것을 시도할 필요가 있습니다.제 해결책은 스택 추적을 생성하고 거기서 발신자의 모듈 이름을 가져오는 것이었습니다.
module.exports = function () {
// generate a stack trace
const stack = (new Error()).stack;
// the third line refers to our caller
const stackLine = stack.split("\n")[2];
// extract the module name from that line
const callerModuleName = /\((.*):\d+:\d+\)$/.exec(stackLine)[1];
return require.main.filename === callerModuleName;
};
다음으로 저장is-main-module.js
이제 다음을 수행할 수 있습니다.
const isMainModule = require("./is-main-module");
if (isMainModule()) {
console.info("called directly");
} else {
console.info("required as a module");
}
어느 쪽이 기억하기가 더 쉽습니까?
먼저, 문제를 더 잘 정의해 보겠습니다.내 생각에 당신이 정말로 찾고 있는 것은 당신의 스크립트가 소유하고 있는지 여부입니다. process.argv
(즉, 스트가담지는여부하당처를리립크process.argv
이러한 가정을 바탕으로 아래의 코드와 테스트는 정확합니다.
module.parent
로 더 하지 않습니다. (이 경우 를 가질 수 .)module.parent
부모만 ). 다음과 같은 경우를 합니다. 따라서 다음과 같은 미래 보장 조건을 사용하여 모든 경우를 처리합니다.
if (
typeof process === 'object' && process && process.argv
&& (
(
typeof module === 'object' && module
&& (
!module.parent
|| require.main === module
|| (process.mainModule && process.mainModule.filename === __filename)
|| (__filename === "[stdin]" && __dirname === ".")
)
)
|| (
typeof document === "object"
&& (function() {
var scripts = document.getElementsByTagName("script");
try { // in case we are in a special environment without path
var normalize = require("path").normalize;
for (var i=0,len=scripts.length|0; i < len; i=i+1|0)
if (normalize(scripts[i].src.replace(/^file:/i,"")) === __filename)
return true;
} catch(e) {}
})()
)
)
) {
// this module is top-level and invoked directly by the CLI
console.log("Invoked from CLI");
} else {
console.log("Not invoked from CLI");
}
다음과 같은 경우 모든 스크립트에서 올바르게 작동하며 오류가† 발생하지 않습니다.
- 가 필요한 x).
require('./main.js')
) - 직접 x).
nodejs cli.js
) - 다른 스크립트(예: x)를 미리 로드하는 중입니다.
nodejs -r main.js cli.js
) - CLI "CLI"("x"))에 합니다.
cat cli.js | nodejs
) - 배관( 예이있예배관는(압: x)).
cat cli.js | nodejs -r main.js
) - 경우(
new Worker('./worker.js')
) eval
교육노예자동예(▁(자동:노▁edenew Worker('if (<test for CLI>) ...', {eval: true})
)- 모듈 내부( ES6 모듈("x"))
nodejs --experimental-modules cli-es6.js
) - "x")가 있는 모듈.
nodejs --experimental-modules -r main-es6.js cli-es6.js
) - 모듈 파이형 ES6예듈(모: x))
cat cli-es6.js | nodejs --experimental-modules
) - 예: x)
cat cli-es6.js | nodejs --experimental-modules -r main-es6.js
) - 경우 입니다.)
process.argv
) - 브라우저 환경:을 통해 하는 경우: ElectronJS)에서 인라인 스크립트와 모든 모듈이 로드되는 경우
<script>
CLI로 됩니다).
하지 않는 이작지않예유는경최스일한우트: x)를 미리 입니다.nodejs -r cli.js cli.js
이할 수 . . . . . . . . . . . . . . . . . . . . 예cat cli.js | nodejs -r cli.js
이는 스크립트를 두 번(필요한 모듈로 한 번, 최상위 수준으로 한 번) 실행하기 때문입니다.미리 로드된 스크립트 내부에서 기본 스크립트가 무엇인지 알 수 없기 때문에 이 문제에 대한 가능한 해결책은 없다고 생각합니다.
† 이론적으로, 오류는 물체에 대한 게터 내부에서 발생할 수 있습니다(예: 누군가가 할 만큼 미친 경우).Object.defineProperty(globalThis, "process", { get(){throw 0} });
그러나 이는 모든 환경에서 코드 스니펫에 사용되는 속성의 기본 상황에서는 절대로 발생하지 않습니다.
유닉스 호출되었는지 모듈 가져오기("node.js" ("node.js" ("node.js" ("node"))를 를 탐지하는 입니까?
import {foo} from 'bar.js'
)이러한 기능은 노출되지 않습니다.현재로서는 CLI와 라이브러리 논리를 별도의 파일로 분리해야 합니다.
node.js 핵심 기여자인 devsnick의 응답이 nodejs/help/issions/2420에 응답합니다.
제 관점에서 옳은 답입니다.
언급URL : https://stackoverflow.com/questions/6398196/detect-if-called-through-require-or-directly-by-command-line
'source' 카테고리의 다른 글
현재 git 브랜치의 이름을 셸 스크립트의 변수로 가져오는 방법은 무엇입니까? (0) | 2023.05.15 |
---|---|
sudo service mongodb restart는 Ubuntu 14.0.4에서 "비활성화된 서비스 오류"를 제공합니다. (0) | 2023.05.15 |
fatal: 초기 EOF fatal: 인덱스 팩 실패 (0) | 2023.05.15 |
작업과 스레드의 차이점 (0) | 2023.05.15 |
Dispose()에서 obj = null(없음)을 설정할 수 있습니까? (0) | 2023.05.15 |