내 계정의 기본 셸이 zsh이지만 터미널을 열고 bash를 시작하고 라는 스크립트를 실행한다고 가정합니다. prac002.sh
zsh 또는 bash 중 어떤 셸 인터프리터가 스크립트를 실행하는 데 사용됩니까? 다음 예를 고려하십시오.
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % sudo cat /etc/passwd | grep papagolf
[sudo] password for papagolf:
papagolf:x:1000:1001:Rex,,,:/home/papagolf:/usr/bin/zsh
# papagolf's default shell is zsh
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % bash
# I fired up bash. (See that '%' prompt in zsh changes to '$' prompt, indicating bash.)
papagolf@Sierra:~/My Files/My Programs/Learning/Shell$ ./prac002.sh
Enter username : Rex
Rex
# Which interpreter did it just use?
**편집:** 스크립트 내용은 다음과 같습니다.
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % cat ./prac002.sh
read -p "Enter username : " uname
echo $uname
답변1
어떤 인터프리터를 사용할지 나타내기 위해 스크립트가 #!
shebang 줄로 시작하지 않기 때문에,POSIX 라고:
만약에
execl()
POSIX.1-2008용 시스템 인터페이스 볼륨에 정의된 [ENOEXEC] 오류에 해당하는 오류로 인해 함수가 실패했습니다.쉘은 검색 결과의 경로 이름을 첫 번째 피연산자로 사용하여 쉘을 호출하는 것과 동일한 명령을 실행해야 합니다., 새 셸의 "$0" 값을 명령 이름으로 설정할 수 있다는 점을 제외하고 나머지 인수를 새 셸에 전달합니다. 실행 파일이 텍스트 파일이 아닌 경우 쉘은 이 명령 실행을 우회할 수 있습니다. 이 경우 오류 메시지를 작성하고 종료 상태 126을 반환해야 합니다.
이 표현은 약간 모호하며 쉘마다 해석이 다릅니다.
이 경우,Bash는 자체적으로 스크립트를 실행합니다.. 반면에 zsh에서 실행하면,zsh는 사용할 것이다sh
(시스템에 있는 모든 것).
이 경우 스크립트에 다음 줄을 추가하여 동작을 확인할 수 있습니다.
echo $BASH_VERSION
echo $ZSH_VERSION
Bash에서 첫 번째 줄은 버전을 인쇄하지만 두 번째 줄은 어떤 셸을 사용하든 아무 것도 표시하지 않습니다.
- 예 를
/bin/sh
들어dash
zsh 또는 dash에서 스크립트를 실행하면 두 줄 모두 아무것도 출력되지 않습니다. - Bash에 연결하는 경우
/bin/sh
모든 경우에 첫 번째 출력 줄이 표시됩니다. - 만약
/bin/sh
그것이라면다른 버전Bash를 직접 사용하는 것과 bash 및 zsh에서 직접 스크립트를 실행하면 다른 출력이 표시됩니다.
이것ps -p $$
롤 답변의 명령스크립트를 실행하기 위해 셸에서 사용하는 명령에 대한 유용한 정보도 표시됩니다.
답변2
파일은 시스템에서 인식하는 어떤 종류의 실행 파일도 아니며 사용자에게 파일 실행 권한이 있다고 가정할 때 시스템 execve()
호출은 일반적으로 다음과 함께 실패합니다 ENOEXEC
.실행파일이 아닙니다) 실수.
다음에 일어날 일은 명령을 실행하는 데 사용되는 응용 프로그램 및/또는 라이브러리 기능에 따라 다릅니다.
execlp()
예를 들어 쉘, / libc 함수일 수 있습니다 execvp()
.
대부분의 다른 응용 프로그램은 명령을 실행할 때 이들 중 하나를 사용합니다. 예를 들어 명령줄을 구문 분석하기 위해 system("command line")
일반적으로 호출되는 libc 함수를 통해 셸을 호출 하거나 sh
(해당 경로는 컴파일 시간에 결정될 수 있음(예: Solaris의 경우 /bin/sh
)) 다음을 사용하는 명령과 같이 자체 /usr/xpg4/bin/sh
저장된 셸을 호출합니다. 또는 다른 많은 명령(대신 사용자의 로그인 쉘을 호출함).$SHELL
vi
!
xterm -e 'command line'
su user -c
$SHELL
일반적으로 시작하지 않는 shebang-less 텍스트 파일은 스크립트 #
로 간주됩니다 sh
. 그러나 구체적인 상황은 sh
다양할 수 있습니다.
execlp()
/ execvp()
, 일반적으로 execve()
반환 시 ENOEXEC
호출됩니다 sh
. 여러 표준을 사용하는 시스템의 경우 sh
여러 표준을 준수할 수 있으므로 이는 sh
일반적으로 컴파일 타임에 결정됩니다(응용 프로그램은 다른 경로를 참조하는 다른 코드 블록을 연결하여 사용 execvp()
/ 링크합니다 ). 예를 들어, Solaris에서는 (표준, POSIX ) 또는 (Solaris 10 및 이전 버전에서는 Bourne 쉘(구식 쉘), Solaris 11에서는 ksh93) 이 됩니다 .execlp()
sh
/usr/xpg4/bin/sh
sh
/bin/sh
조개껍질에는 다양한 변형이 있습니다. bash
, AT&T, Bourne 쉘은 일반적으로 (하위 프로세스를 사용하지 않는 한) 시뮬레이션 후 스크립트 자체를 해석합니다. ksh
즉, 내보내지 않은 모든 변수를 설정 해제하고, 실행 시 닫기 fd를 모두 닫고, 모든 사용자 정의 트랩, 별칭, 함수를 제거합니다... .(스크립트 모드에서 해석됩니다). 그것을 해석하기 위해 자체적으로 실행됩니다(모드에서 그렇게 사용).exec
execve()
bash
sh
yash
sh
argv[0]
sh
zsh
pdksh
, 을 기반으로 하는 쉘이 ash
일반적으로 호출됩니다 sh
(해당 경로는 컴파일 타임에 결정됩니다).
csh
and tcsh
(및 일부 초기 BSD) 의 sh
경우 파일의 첫 번째 문자가 #
이면 해석하기 위해 스스로 실행되고 sh
그렇지 않으면 실행됩니다. 이것은 csh
실제로 #
주석으로 인식되었지만 Bourne 쉘에서는 인식되지 않았던 Shebang 이전 시대로 거슬러 올라갑니다. 따라서 #
csh 스크립트임을 암시합니다.
fish
(최소 버전 2.4.0) execve()
실패하면 오류만 반환합니다(스크립트로 처리하려고 시도하지 않음).
일부 쉘(예: bash
AT&T ksh
)은 먼저 파일이 스크립트일 수 있는지 경험적으로 판단하려고 시도합니다. 따라서 스크립트의 처음 몇 바이트에 NUL 문자가 있는 경우 일부 쉘은 스크립트 실행을 거부할 수 있습니다.
또한 execve()
ENOEXEC가 실패했지만 파일에 shebang 줄이 있으면 일부 쉘은 shebang 줄 자체를 해석하려고 시도합니다.
몇 가지 예를 들면 다음과 같습니다.
- 이면 in 모드로
$SHELL
해석/bin/bash
됩니다 . 그리고 using이 사용되므로 스크립트가 해석됩니다.xterm -e 'myscript with args'
myscript
bash
sh
xterm -e myscript with args
xterm
execvp()
sh
su -c myscript
root
로그인 쉘이 Bourne/bin/sh
쉘인 Solaris 10에서는 Bourne 쉘이 해석/bin/sh
됩니다myscript
./usr/xpg4/bin/awk 'BEGIN{system("myscript")'
/usr/xpg4/bin/sh
Solaris 10에서는 (와 동일 ) 로 해석됩니다/usr/xpg4/bin/env myscript
.find . -prune -exec myscript {} \;
Solaris 10(사용)에서는 POSIX 환경에서도 Evenexecvp()
로 해석됩니다 (일관성 오류)./bin/sh
/usr/xpg4/bin/find
csh -c myscript
csh
로 시작하면 그렇지 않은#
것으로 해석됩니다sh
.
요약하자면, 스크립트가 어떻게, 무엇에서 호출되는지 모르면 스크립트를 해석하는 데 어떤 셸을 사용할지 결정할 수 없습니다.
어쨌든 read -p
이는 단지 bash
구문일 뿐이므로 스크립트가 해석되었는지 확인해야 합니다 bash
(그리고 오해의 소지가 있는 .sh
확장을 피해야 함). 실행 파일의 경로를 알고 bash
다음을 사용합니다.
#! /path/to/bash -
read -p ...
또는 다음 명령을 사용하여 실행 파일을 $PATH
찾을 수 있습니다 bash
(설치되어 있다고 가정).bash
#! /usr/bin/env bash
read -p ...
( env
거의 모든 곳에서 /usr/bin
). 또는 POSIX+Bourne과 호환되게 만들 수 있으며, 이 경우 /bin/sh
./bin/sh
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"
답변3
어떤 셸이 사용되는지 확인하려면 다음 스크립트를 실행할 수 있습니다.
ps -p $$
echo -n "The real shell is: "
realpath /proc/$$/exe
내 컴퓨터에서 나는
PID TTY TIME CMD
13718 pts/16 00:00:00 sh
The real shell is: /usr/bin/bash
내 기본 쉘이다루기 힘든. 그것은 사용한다세게 때리다내 컴퓨터에서는쉿명령은 다음을 통해 구현됩니다.세게 때리다그리고다루기 힘든추천쉿shebang이 지정되지 않은 경우.