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


12

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

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

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

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

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

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


2
당신은 할 수 없었습니다. 그것을 제거하고 모든 스크립트를 실행하십시오/bin/bash -x "$script"
jesse_b


... 일반적으로이 시점에 도달 할 때까지는 이미 쉘 스크립트 사용을 중단하고 실제 스크립팅 언어를 사용하여 작업을 수행 할 시간이라고 결론을 내 렸습니다.
Shadur

답변:


19

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

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

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

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

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


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


대답은 다음과 같이 확장되어야합니다 #!. 파일에 실행 가능한 권한이 있고 인터프리터가 아니라 셸이 파일을로드하면 셸 이 행으로 인터프리터를 결정합니다 . 즉, 행이 있고 (perl 인터프리터를 가리키는) 파일에 exec 권한이있는 /path/to/myprog.pl경우 perl 프로그램을 실행하십시오 #!.
rexkogitans

11

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

따라서 스크립트가 존재 #!/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에서 실행되며 프로세스 목록에서 명시 적으로 볼 수 있습니다.


ps -aux경고를 줄 수 있습니다
Weijun 저우에게

@WeijunZhou 더 말해 ...
Kusalananda

일부 버전은 ps경고 를 제공합니다 Warning: bad syntax, perhaps a bogus '-'?.
Weijun Zhou

2
psBSDUXIX 인수 구문을 모두 지원 합니다. -aux유닉스 스티븐은 아마도 aux올바른 BSD를 의미 할 것입니다
Jasen

1
사람, 2 가지; 상기 예 개념합니다 (있는지에 (1) 포커스 ps쇼의 호출 bash)이 아닌 명백한 문법; (2) ps -auxCentOS 7 및 Debian 9에서 경고없이 완벽하게 작동합니다. 그 cut'n'paste는 정확히 내 컴퓨터의 출력이었습니다. -필요 여부에 대한 전체 논의는 현재 버전이 아닌 이전 버전의 Linux procp에 적용 할 수 있습니다.
Stephen Harris

9

의 위에 .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 진수를 배우십시오. 어쨌든 읽을 수 있습니다.


1
흠, 확장자는 반드시 나쁘지는 않지만 최소한 파일 형식이 다른 사용자와 통신하는 데 도움이됩니다.
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy 그러나 당신은 언어를 알 필요가 없습니다, 당신은 그것을 실행해야합니다. 심지어 Microsoft조차도 확장 기능에서 벗어나려고합니다 (불행히도 내 숨어 숨기고 있습니다). 그러나 나는 그들이 좋은 아이디어가 될 수 있다는 데 동의합니다 .image. .audio구현 / 인코딩에 관한 것이 아니라 그것이 무엇인지 말해줍니다.
ctrl-alt-delor

1
@ ctrl-alt-delor 파일이 호출 launch-missiles되거나 delete-project-and-make-manager-pissed언어에 대해서만 궁금했을 때 "그냥 실행"하고 싶지 않으면 :)
Sergiy Kolodyazhnyy

2
언어가 궁금하다면 file명령을 사용하십시오 . 대부분의 파일 형식을 인식합니다.
Jasen

2
나는 확장이 실행 스크립트에 나쁘다는 것에 동의합니다. 왜냐하면 나는 다른 쉘 스크립트 (즉, 실행 불가능한 스크립트)에 의해 소스되어야하는 스크립트에 .sh 확장자를 사용합니다. 그 시나리오에서 접미사는 파일 사용 방법을 알려주므로 중요 / 유효합니다.
Laurence Renshaw 0시 54 분

8

[해시 뱅 라인] 은 다른 쉘이 사용 된 경우 예기치 않은 동작을 방지하기 위해 스크립트가 특정 쉘 (이 경우에는 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 구현으로 직접 바꿀 수는 없다는 것입니다.


bash 배열의 경우 +1 다중 쉘 또는 POSIX에서 정의한 일부에 익숙하지 않은 사용자 는 한 쉘의 일부 기능이 다른 쉘에 있다고 가정 할 수 있습니다 . 또한 기능과 관련하여 다음과 같이 관련 될 수 있습니다. unix.stackexchange.com/q/313256/85039
Sergiy Kolodyazhnyy

4

일부 주 파일에서 "전역"스크립트 선언을 사용하여 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)로만 실행되도록합니다.

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


1

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

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

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

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

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

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

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

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

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


좋은 답변 주셔서 감사합니다. 나는 대답의 모든 것을 사랑했고 이것까지 찬성을 생각했다 then you should learn what the #! line is really for, and keep using it in every executable script!. 특정 지식의 관점에서 U.Philosophy를 따를 수 있습니다. 이 모든 대답을 마친 후에 왜 그것이 그 용어에 포함될 수 있는지 이해했습니다. 나는 "당신이 존중하고 채택하는 유닉스 철학의 내부 부분으로 shebang을 보자"로 대체하여 답을 편집 할 것을 제안한다.
user9303970

1
내가 직접적이거나 그 의견이 무례한 것 같으면 미안합니다. 귀하의 의견에 따르면 해당 프로젝트 내에서 스크립트에 대한 전역 규칙을 정의 할 수있는 '프로젝트'를 사용하여 IDE에서 작업하는 것을 선호한다고 제안했습니다. 이 방법은 개발하기에 적합한 방법이지만 각 스크립트를 독립적 인 독립형 프로그램 (여러분이 언급 한 Unix 철학)으로 취급하는 데 적합하지 않습니다.
Laurence Renshaw 3:10에
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.