Universal Node.js shebang?

Universal Node.js shebang?

Node.js요즘 꽤 인기가 많아서 그걸 이용해서 스크립트를 작성하고 있어요. 불행히도 호환성이 문제입니다. 공식적으로 Node.js 인터프리터는 으로 호출되어야 node하지만 Debian과 Ubuntu는 nodejs.

나는 가능한 한 많은 상황에서 사용할 수 있는 Node.js 이식 가능한 스크립트를 원합니다. 파일 이름이 이라고 가정하면 foo.js스크립트가 두 가지 방법으로 실행되기를 원합니다.

  1. ./foo.jsnode또는 nodejs가 에 있으면 스크립트를 실행합니다 $PATH.
  2. node foo.js또한 스크립트를 실행합니다(인터프리터가 호출된다고 가정 node).

노트:xavierm02와 내 답변은 다국어 스크립팅의 두 가지 변형입니다. 나는 순수한 shebang 솔루션이 존재한다면 여전히 관심이 있습니다.

답변1

내가 생각해낸 최고는 실제로 다중 언어(Bourne shell/Node.js) 스크립트인 "두 줄 셰뱅"입니다.

#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"

console.log('Hello world!');

분명히 첫 번째 줄은 Bourne shell shebang입니다. Node.js는 찾은 모든 shebang을 우회하므로 Node.js에 관한 한 이는 유효한 자바스크립트 파일입니다.

:두 번째 줄은 인수를 사용하여 쉘 no-op를 호출 //한 다음 파일 이름을 인수로 사용하여 실행합니다 nodejs. 이식성을 대신하여 사용됩니다. 명령 대체 구문은 엄밀히 말하면 Bourne이 아니므로 1980년대에 이 명령을 실행하는 경우 백틱을 선택하십시오.nodecommand -vwhich$(...)

Node.js는 아무 작업도 하지 않는 것처럼 작동하는 문자열을 평가하고 ':'나머지 줄은 주석으로 구문 분석됩니다.

파일의 나머지 부분은 평범한 오래된 JavaScript입니다. 서브쉘은 exec두 번째 줄이 완료된 후에 종료되므로 쉘은 파일의 나머지 부분을 읽지 않습니다.

영감을 주신 xavierm02와 추가 정보를 주신 모든 댓글 작성자에게 감사드립니다!

답변2

이는 정책이 의미를 극복하는 데비안 기반 시스템에서만 발생하는 문제입니다.

Fedora가 nodejs라는 바이너리를 언제 제공했는지는 모르겠지만 본 적이 없습니다. 패키지는 nodejs라고 하며 node.js라는 바이너리를 설치합니다.

심볼릭 링크를 사용하여 데비안 기반 시스템에 상식을 적용하면 제정신인 Shebang을 사용하는 것이 좋습니다. 어쨌든 다른 사람들은 정상적인 shebang을 사용하므로 해당 심볼릭 링크가 필요합니다.

#!/usr/bin/env node

console.log("Spread the love.");

답변3

#!/bin/sh
//bin/false || `which node || which nodejs` << `tail -n +2 $0`
console.log('ok');

//bin/false/bin/false두 번째 슬래시가 노드에 대한 주석으로 바뀌는 것과 동일합니다 . 이것이 바로 여기에 있는 이유입니다. 그런 다음 첫 번째 항목의 오른쪽을 ||평가합니다 . 'which node || which nodejs'따옴표 대신 백틱을 사용하여 노드를 시작하고 <<오른쪽에 있는 내용을 지정합니다. 이렇게 dancek로 시작하는 구분 기호를 사용할 수도 //있고 작동할 수도 있지만 처음에 두 줄만 사용하는 것이 더 깔끔하다는 것을 알았기 때문에 tail -n +2 $0처음 두 줄을 제외하고 파일 자체를 읽도록 두곤 했습니다.

node에서 실행하면 첫 번째 줄은 shebang으로 인식되어 무시되고, 두 번째 줄은 한 줄 주석이 됩니다.

(물론 tail 대신 sed를 사용할 수도 있습니다.첫 번째 줄과 마지막 줄을 제외하고 파일 내용을 인쇄합니다.)


편집하기 전에 대답하십시오:

#!/bin/sh
`which node || which nodejs` <<__HERE__
console.log('ok');
__HERE__

원하는 것을 할 수 없으므로 쉘 스크립트를 실행해야 합니다 #!/bin/sh. 따라서 쉘 스크립트는 노드를 실행하는 데 필요한 파일의 경로를 가져옵니다. 즉, 노드 which node || which nodejs가 실행되도록 백틱이 여기에 있습니다. 따라서 'which node || which nodejs'(따옴표 대신 백틱 사용) node.js를 호출하면 됩니다. 그런 다음 스크립트의 구분 기호입니다 <<. __HERE__이는 console.log('ok');예제 스크립트이므로 사용자의 스크립트로 바꿔야 합니다.

답변4

완성도를 높이기 위해 두 번째 줄을 실행하는 다른 방법은 다음과 같습니다.

// 2>/dev/null || echo yes
false //|| echo yes

그러나 어느 쪽도 선택한 답변보다 이점을 제공하지 않습니다.

':' //; || echo yes

node또는 둘 중 하나만 찾을 수 있다는 것을 알고 있는 경우 nodejs다음을 수행할 수 있습니다.

exec `command -v node nodejs` "$0" "$@"

하지만 그것은 큰 "만약"이기 때문에 선택한 답변이 여전히 가장 좋은 답변이라고 생각합니다.

관련 정보