커널에 실행 방법을 알려 주는 두 글자
./script.sh 실행하면 커널이 파일의 첫 두 바이트를 읽어. #!(shebang)이면 첫 줄의 나머지를 인터프리터 경로로 해석해. 커널은 그 인터프리터에 스크립트 경로를 인자로 전달해.
휴대성 있는 모양
#!/usr/bin/env bash
#!/usr/bin/env zsh
#!/usr/bin/env python3
#!/bin/sh/usr/bin/env는 현재 PATH에서 인터프리터를 찾아. 그래서 Homebrew로 설치한 새 bash처럼 위치가 다른 실행 파일도 고를 수 있어. 다만 유연하다는 말은 곧 선택 결과가 환경마다 달라질 수 있다는 뜻이야. 개발자 도구에는 편하지만, 배포 환경에서 정확히 같은 인터프리터가 필요하면 검증된 절대 경로가 더 안전해.
실행 권한
chmod +x script.sh
./script.shchmod +x로 실행 권한을 주지 않으면 커널이 직접 실행을 거부해. 다만 bash script.sh처럼 인터프리터를 직접 지정하면 실행 권한이나 shebang과 관계없이 그 bash가 파일을 읽어.
셸 문법과 첫 줄을 맞춰라
첫 줄은 sh라고 해 놓고 본문에서 bash 전용인 [[ ... ]]를 쓰면 실행 환경에 따라 바로 깨져. 휴대성이 필요하면 POSIX sh 문법만 쓰고, bash 기능을 썼다면 bash를 명시해. 중요한 건 어느 표기가 더 멋진지가 아니라 본문이 요구하는 셸과 실행 계약이 일치하는지야.
유연성과 재현성은 서로 당겨
/usr/bin/env bash는 PATH에서 bash를 찾아 개발자가 설치한 버전을 쓰기 편해. 반대로 한 번 검증한 인터프리터가 꼭 필요한 배포라면 관리되는 절대 경로를 지정하는 편이 더 안전할 수 있어.
호출자는 shebang을 덮어쓸 수 있어
bash script.sh는 그 bash가 파일을 직접 읽게 해. 실행 권한과 shebang은 파일 자체를 ./script.sh로 호출할 때 적용돼.
확장자가 아니라 첫 줄이 계약이야
.sh 확장자는 문법을 선택하지 않아. 파일을 직접 실행하면 shebang이 인터프리터를 정하고, bash file처럼 호출자가 인터프리터를 명시하면 그 선택이 shebang보다 우선해.