Shebang (스크립트 선언) 줄이 너무 많음 — 양을 줄일 수있는 방법이 있습니까? 스크립트가 특정 쉘 (이

약 20 개의 작은 .sh파일로 구성된 프로젝트가 있습니다. 일반적으로 파일의 코드가 20 줄을 초과하지 않기 때문에이 이름을 “작음”으로 지정합니다. 나는 유닉스 철학에 충실하기 때문에 모듈 식 접근 방식을 취 했으며 프로젝트를 유지하는 것이 더 쉽습니다.

.sh파일 의 시작 부분 에을 넣습니다 #!/bin/bash.

간단히 말해서 스크립트 선언에는 두 가지 목적이 있습니다.

  1. 파일을 사용하지 않고 몇 년 후에 파일을 실행하는 데 필요한 쉘을 사용자가 기억하도록 도와줍니다.
  2. 다른 쉘이 사용 된 경우 예기치 않은 동작을 방지하기 위해 스크립트가 특정 쉘 (이 경우에는 Bash)로만 실행되도록합니다.

프로젝트가 5 개 파일에서 20 개 파일로 또는 20 개 파일에서 50 개 파일로 증가하기 시작하면 (이 경우가 아니라 단순히 설명하기 위해) 20 줄 또는 50 의 스크립트 선언이 있습니다. 나는 그것이 일부 사람들에게는 재미있을지라도 인정하지만, 프로젝트 당 1 또는 20을 사용하는 대신 약간의 중복성을 느낍니다 ( 프로젝트주 파일 에있을 수 있음).

일부 주 파일에서 “전역”스크립트 선언을 사용하여 20 또는 50 또는 이보다 많은 수의 스크립트 선언 줄을 피할 수있는 방법이 있습니까?



답변

프로젝트가 이제 50 개의 Bash 스크립트로만 구성되어 있어도 조만간 Perl 또는 Python과 같은 다른 언어로 작성된 스크립트가 누적되기 시작합니다 (이 스크립트 언어에는 Bash에는없는 이점이 있습니다).

#!각 스크립트에 적절한 줄이 없으면 어떤 인터프리터를 사용해야하는지 알지 못하면 다양한 스크립트를 사용하는 것이 매우 어려울 것 입니다. 모든 단일 스크립트가 다른 스크립트에서 실행되는지는 중요하지 않으므로 최종 사용자에서 개발자로 어려움을 옮깁니다. 이 두 그룹의 사람들은 스크립트를 사용하기 위해 어떤 언어로 스크립트를 작성했는지 알 필요가 없습니다.

셸 스크립트 #!는 명시 적 인터프리터없이 온라인으로 실행되는 셸은 호출하는 셸에 따라 다른 방식으로 실행됩니다 (예 : Shebang없이 스크립트를 실행하는 셸 인터프리터 , 특히 Stéphane ‘s answer 질문 참조 ). 프로덕션 환경에서 (일관된 동작 및 심지어 이식성을 원할 경우).

명시 적 인터프리터로 실행 된 스크립트는 #!-line 의 내용에 관계없이 해당 인터프리터에 의해 실행됩니다 . 예를 들어 파이썬이나 다른 언어로 Bash 스크립트를 다시 구현하기로 결정하면 문제가 발생할 수 있습니다.

추가 키 입력을 사용하고 항상 #!각 스크립트마다 줄을 추가해야합니다 .


일부 환경에서는 각 프로젝트의 각 스크립트에 여러 단락 상용구 법률 텍스트가 있습니다. #!프로젝트에서 “중복”된 느낌을 주는 유일한 라인이라는 사실에 매우 만족하십시오 .


답변

의 요점을 오해합니다 #!. 실제로 운영 체제가 정의 된 인터프리터에서이 프로그램을 실행 하도록 지시 합니다.

따라서 스크립트가 존재 #!/usr/bin/perl하고 결과 프로그램이 실행될 수 있으며 ./myprogramperl 인터프리터가 사용될 수 있습니다. 마찬가지로 #!/usr/bin/python파이썬에서 프로그램이 실행됩니다.

따라서이 줄 #!/bin/bash은 OS에게 bash에서이 프로그램을 실행하도록 지시합니다.

예를 들면 다음과 같습니다.

$ echo $0
/bin/ksh

$ cat x
#!/bin/bash

ps -aux | grep $$

$ ./x
sweh      2148  0.0  0.0   9516  1112 pts/5    S+   07:58   0:00 /bin/bash ./x
sweh      2150  0.0  0.0   9048   668 pts/5    S+   07:58   0:00 grep 2148

따라서 쉘이 ksh 임에도 불구하고 프로그램 “x”는 #!줄 때문에 bash에서 실행되며 프로세스 목록에서 명시 적으로 볼 수 있습니다.


답변

의 위에 .sh

나쁜 점은 .sh파일 이름 끝에 있습니다.

파이썬에서 스크립트 중 하나를 다시 작성한다고 상상해보십시오.

이제 #!/usr/bin/python3파일의 다른 모든 코드 줄도 변경해야 했으므로 첫 번째 줄을 이렇게 변경해야합니다. 그러나 파일 이름을에서 (으) prog.sh로 변경해야합니다 prog.py. 그런 다음 다른 스크립트와 모든 사용자 스크립트 (알지 못하는 스크립트)를 찾아 새 스크립트를 사용하도록 변경해야합니다. sed -e 's/.sh/.py/g'당신이 아는 사람들을 도울 수 있습니다. 그러나 이제 개정 관리 도구는 관련없는 많은 파일의 변경 사항을 보여줍니다.

또는 유닉스 방식으로 프로그램 이름을 지정 prog하지 마십시오 prog.sh.

의 위에 #!

올바른 경우 #!, 실행을 포함하도록 권한 / 모드를 설정하십시오. 그런 다음 통역사를 알 필요가 없습니다. 컴퓨터가 당신을 위해 그것을 할 것입니다.

chmod +x prog #on gnu adds execute permission to prog.
./prog #runs the program.

gnu가 아닌 시스템의 경우 설명서를 읽고 chmod8 진수를 배우십시오. 어쨌든 읽을 수 있습니다.


답변

[해시 뱅 라인] 은 다른 쉘이 사용 된 경우 예기치 않은 동작을 방지하기 위해 스크립트가 특정 쉘 (이 경우에는 Bash)로만 실행되도록합니다.

아마도 이것이 틀렸다는 것을 지적 할 가치가 있습니다. hashbang 줄은 파일을 잘못된 셸 / 인터프리터로 공급하는 것을 막지 않습니다.

$ cat array.sh
#!/bin/bash
a=(a b c)
echo ${a[1]} $BASH_VERSION
$ dash array.sh
array.sh: 2: array.sh: Syntax error: "(" unexpected

(또는 이와 유사하게 awk -f array.sh)


그러나 어쨌든 모듈화에 대한 또 다른 접근 방식은 파일에서 쉘 기능, 파일 당 하나의 기능, 원하는 경우 source주 프로그램의 파일을 정의하는 것입니다. 이렇게하면 해시 뱅이 필요하지 않습니다. 해시 뱅은 다른 주석으로 취급되며 모든 것이 동일한 셸을 사용하여 실행됩니다. 단점은 source함수 (예 :)가있는 파일이 필요 for x in functions/*.src ; do source "$x" ; done하고 모두 동일한 쉘을 사용하여 실행되므로 그중 하나를 Perl 구현으로 직접 바꿀 수는 없다는 것입니다.


답변

일부 주 파일에서 “전역”스크립트 선언을 사용하여 20 또는 50 또는 이보다 많은 수의 스크립트 선언 줄을 피할 수있는 방법이 있습니까?

휴대 성 또는 POSIX 준수라고합니다. 항상 이식 가능하고 쉘 중립적 인 방식으로 스크립트를 작성하도록 노력하고 대화식으로 사용하는 스크립트 #!/bin/sh/bin/shPOSIX 호환 쉘 (예 : ksh.

그러나 이식 가능한 스크립트는 다음을 저장하지 않습니다.

  • 껍질 중 하나의 기능을 사용해야 할 필요가 있습니다 ( ilkkachu의 대답 은 예입니다)
  • 쉘 (Python 및 Perl)보다 고급 스크립팅 언어를 사용해야 함
  • PEBKAC 오류 : 스크립트는하지로 스크립트를 실행하는 사용자 J.Doe의 손에 떨어진다 예를 들어 그들이 실행을 목적 /bin/sh으로 스크립트를 csh.

내 의견을 표현할 수 있다면 “중복을 피하는 것” #!은 잘못된 목표입니다. 목표는 일관된 성능과 실제로 작동하고 코너 사례를 고려하는 작동 하는 스크립트 이어야하며 구문 분석하지 않음 -1 또는 항상 인용 변수-필요없는 단어 분리 와 같은 특정 규칙을 따릅니다 .

파일을 사용하지 않고 몇 년 후에 파일을 실행하는 데 필요한 쉘을 사용자가 기억하도록 도와줍니다.

그들은 실제로 사용자를위한 것이 아닙니다. 운영 체제가 적절한 인터프리터를 실행하는 것입니다. 이 경우 “적절한”은 OS가 shebang에있는 것을 찾는 것을 의미합니다. 잘못된 쉘에 대해 아래 코드가 있으면 저자의 잘못입니다. 사용자 메모리에 관해서는, Microsoft Word 또는 Chrome과 같은 프로그램의 “사용자”는 어떤 언어 프로그램이 작성되었는지 알 필요가 없다고 생각합니다. 저자가 필요할 수 있습니다.

그런 다음 이식 가능하게 작성된 스크립트는 이식 가능한 스크립트가 POSIX 호환 쉘에서 작동해야하기 때문에 원래 사용했던 쉘을 기억할 필요가 없습니다.

다른 쉘이 사용 된 경우 예기치 않은 동작을 방지하기 위해 스크립트가 특정 쉘 (이 경우에는 Bash)로만 실행되도록합니다.

그들은하지 않습니다. 실제로 예기치 않은 동작을 방지하는 것은 이식 가능한 스크립트를 작성하는 것입니다.


답변

#!/bin/bash각 스크립트의 맨 위에 배치해야하는 이유 는 별도의 프로세스로 스크립트를 실행하기 때문입니다.

스크립트를 새로운 프로세스로 실행할 때, OS는 스크립트가 이진 실행 파일이 아닌 텍스트 파일임을 인식하고 실행할 인터프리터를 알아야합니다. 말하지 않으면 OS는 기본 설정 (관리자가 변경할 수 있음) 만 사용하여 추측 할 수 있습니다. 따라서 #!행 (물론 실행 권한 추가와 함께)은 간단한 텍스트 파일을 직접 실행할 수있는 실행 파일로 변환하여 OS가 수행 할 작업을 알고 있음을 확신합니다.

#!줄 을 제거하려면 옵션은 다음과 같습니다.

  1. 스크립트를 직접 실행하고 (현재하고있는 것처럼)
    기본 인터프리터가 스크립트와 일치하기를 바랍니다 . 대부분의 Linux 시스템에서는 안전하지만 다른 시스템 (예 : Solaris)으로 이식 할 수 없으며 다음과 같이 변경할 수 있습니다 무엇이든 ( vim파일 에서 실행되도록 설정할 수도 있습니다!).

  2. 를 사용하여 스크립트를 실행하십시오 bash myscript.sh. 이것은 잘 작동하지만 스크립트 경로를 지정해야하며 지저분합니다.

  3. . myscript.sh현재 인터프리터 프로세스 내에서 (즉, 하위 프로세스가 아닌) 스크립트를 실행하는을 사용하여 스크립트를 소싱 하십시오 . 그러나 이것은 거의 확실하게 스크립트를 수정해야하며 모듈 / 재사용 성이 떨어집니다.

사례 2와 3의 경우 파일에 실행 권한이 필요하지 않으며 필요하지 않아야하며 접미사 .sh(또는 .bash)를 부여 하는 것이 좋습니다.

그러나 스크립트를 모듈 식으로 유지하고 싶다고 말했듯이 (=> 독립적이고 독립적 인) 이러한 옵션 중 어느 것도 프로젝트에 적합하지 않으므로 #!/bin/bash스크립트를 맨 위에 유지해야합니다 .

귀하의 질문에서, 당신은 또한 당신이 유닉스 철학을 따르고 있다고 말했습니다. 그것이 사실이라면, 그 #!줄이 실제로 무엇인지 배우고 모든 실행 가능한 스크립트에서 계속 사용하십시오!


답변