이중 하이픈 (-)으로 시작하는이 shebang은 어떻게 작동합니까?


14

RosettaCode 페이지에서 다음과 같은 종류의 shebang을 발견했습니다.

--() { :; }; exec db2 -txf "$0"

Db2에서도 작동하며 Postgres에서도 마찬가지입니다. 그러나 나는 전체 라인을 이해하지 못합니다.

이중 대시는 SQL에서 주석이며 그 후에 파일 자체를 파일로 전달하는 일부 매개 변수를 사용하여 Db2 실행 파일을 호출합니다. 그러나 괄호, 중괄호, 콜론 및 세미콜론은 어떻습니까? ?

https://rosettacode.org/wiki/Multiline_shebang#PostgreSQL

답변:


18

관련 : 어떤 쉘 인터프리터가 shebang없이 스크립트를 실행합니까?

스크립트에는 #!이중 대시가 없기 때문에 shebang / hashbang / 행이 없습니다 #!.

그러나 스크립트는 쉘 (위의 링크 된 질문 및 답변 참조)에 의해 실행되며 해당 쉘 -에서 함수 이름에 유효한 문자 인 경우 행은 --아무 것도하지 않는 쉘 함수를 선언합니다 (잘 실행됩니다 :. 어느 것도 수행하지 않으며 결코 호출되지 않습니다.

더 일반적인 여러 줄 표기법의 함수 (홀수 이름이 실제로 함수라는 사실을 모호하기 때문에 모양을보다 명확하게하기 위해) :

-- () {
  :
}

함수 정의의 유일한 목적은 쉘 스크립트에서 유효하고 동시에 유효한 SQL 명령 (주석)을 갖는 것입니다. 이러한 종류의 코드를 폴리 글롯 이라고합니다 .

가짜 쉘 함수를 선언 한 후, 스크립트는 쉘 스크립트 인터프리터에 의해 실행될 때 exec현재 쉘을 명령 실행에서 스크립트의 경로명에서 db2 -txf "$0"사용하는 것과 동일한 실행 결과 프로세스로 대체하는 데 사용 됩니다 db2 -txf.

이 트릭은 이름이 대시를 포함하는 함수를 허용하지 않기 때문에 dash또는 다른 ash기반 쉘, yashBourne 쉘 ksh88또는 ksh93로 사용되는 시스템에서는 안정적으로 작동 /bin/sh하지 않을 수 있습니다.

또한 관련 :


다음과 같이 작동한다고 가정합니다 (실제 테스트되지는 않음).

--() { exec db2 -txf "$0"; }; --

@ilkkachu 더 나은 지금?
Kusalananda

1
어 그래! 그런 종류의 것이 무엇인지 상기시켜 주셔서 감사합니다. :)
ilkkachu

6

@ Kusalananda가 이미 말했듯이 그 트릭은 깨졌으며 모든 쉘에서 작동하지는 않습니다.

다음은 이식 가능하게 수행하는 것입니다.

--/.. 2>/dev/null; exec db2 -txf "$0"

첫 번째 명령은 이름 --이 지정된 파일 / 디렉토리 가 현재 디렉토리에 존재 하더라도 오류가 발생하고 2>/dev/null; 그런 다음 쉘은 두 번째 명령 인 exec.


여전히 휴대가 쉽지 않습니다. 유효한 스크립트가 아니며 커널이 스크립트 실행을 거부하고 ENOEXEC시도하면 반환한다는 사실을 해결하기 위해 여전히 호출 쉘에 의존하고 있습니다. 아래에서 스크립트를 실행하여 strace의미하는 바를 확인하십시오.
kasperd

@kasperd, 그것은 여전히 ​​휴대용이어야하며, 쉘은 exec()작동하지 않으면 쉘 스크립트로 스크립트를 실행해야 합니다. "[ENOEXEC] 오류와 동등한 오류로 인해 execl () 함수가 실패하면, 쉘은 첫 번째 피연산자 인 명령 이름으로 쉘을 호출하는 것과 동등한 명령을 실행해야합니다 ..." ( pubs.opengroup 참조) .org / onlinepubs / 9699919799.2018edition / utilities /… )
ilkkachu

@ilkkachu 그러나 스크립트가 항상 쉘에서 실행되는 것은 아닙니다. 실행 파일이 작동하는 다른 컨텍스트에서 스크립트를 사용하려고하면 실패합니다. 또한 쉘은 어떤 인터프리터를 사용할지 동의하지 않습니다. 따라서 스크립트는 어떤 컨텍스트에서 호출되는지에 따라 다르게 동작하거나 실패합니다.
kasperd

@kasperd, 글쎄, exec()쉘 이외의 다른 것에서 직접 작동하면 작동하지 않습니다 . 그러나 그 사건은 무엇입니까? 스크립트를 실행하고 싶을 수도 cron있지만 어쨌든 셸을 통해 모든 것을 실행한다고 생각하지만 그렇지 않은 경우에도 db2 -txf /path/to/script한 번만 수행하면되므로 철자를 쉽게 입력 할 수 있습니다. 속기 작업은 대화식 쉘에서 주로 유용합니다. 그러나 별도의 래퍼 스크립트가 더 강력 할 수 있습니다.
ilkkachu

1
@kasperd 나는 문서와 표준으로 당신을 괴롭히지 않을 것이다. 그냥 시도 해 봐! echo 'int main(int c,char**a){execvp(a[1],a+1);}' | cc -include unistd.h -xc -; echo echo yeah > a.sh; chmod 755 a.sh; ./a.out ./a.sh; PATH=`pwd` ./a.out a.sh
Billy 아저씨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.