>

질문:

  • 쉘 스크립트를 shebang 라인에 꽂으면 커널은 무엇을 하는가?
  • 커널은 어떤 인터프리터를 시작할지 어떻게 알 수 있습니까?

설명:

최근에 CGI 환경에서 전역을 제외하고PATH변수를 설정할 수 없기 때문에/usr/bin/env주위에 래퍼를 작성하고 싶었습니다. 물론 짜증나!).

따라서 "OK. PREPENDPATH를 설정하고 env 주위의 래퍼에PATH를 설정하겠습니다."라고 생각했습니다. 결과 스크립트 (여기서는env.1)는 다음과 같습니다.

#!/bin/bash
/usr/bin/env PATH=$PREPENDPATH:$PATH $*

작동하는 것처럼 보입니다. PREPENDPATH를 설정 한 후 둘 다 어떻게 반응하는지 확인했습니다.

$ which /usr/bin/env python
/usr/bin/env
/usr/bin/python
$ which /usr/bin/env.1 python
/usr/bin/env
/home/pi/prepend/bin/python

완전히완벽을 보라! 여태까지는 그런대로 잘됐다. 그러나 "Hello World!"는 어떻게되는지보십시오.

# Shebang is #!/usr/bin/env python
$ test-env.py
Hello World!
# Shebang is #!/usr/bin/env.1 python
$ test-env.1.py
Warning: unknown mime-type for "Hello World!" -- using "application/*"
Error: no such file "Hello World!"

UNIX에 대한 근본적인 내용이 누락 된 것 같습니다.

원본env의 소스 코드를 본 후에도 꽤 길을 잃었습니다. 환경을 설정하고 프로그램을 시작합니다 (또는 나에게 보입니다 ...).

  • 답변 # 1

    먼저 $* 를 거의 사용하지 않아야합니다.  거의 항상 "[email protected]" 를 사용해야합니다.  대신에. 여기 SO에 대한 여러 가지 질문이 있으며 그 이유와 그 이유를 설명합니다.

    두 번째- env  명령에는 두 가지 주요 용도가 있습니다. 하나는 현재 환경을 인쇄하는 것입니다. 다른 하나는 명령이 실행될 때 명령 환경을 완전히 제어하는 ​​것입니다. 세 번째 용도는 환경을 수정하는 것이지만 솔직히 그럴 필요는 없습니다. 셸은이를 처리 할 수 ​​있습니다.

    모드 1 :

    env
    
    

    모드 2 :

    env -i HOME=$HOME PATH=$PREPENDPATH:$PATH ... command args
    
    

    이 버전은 상속 된 모든 환경 변수를 취소하고 command 를 실행합니다.  ENVVAR = 값 옵션에 의해 설정된 환경과 정확하게 일치합니다.

    환경을 개선하는 세 번째 모드는 일반 (문명화 된) 셸로 잘 수행 할 수 있기 때문에 덜 중요합니다. (이것은 "C 쉘이 아님"을 의미합니다. 다시 말하지만, SO에 대한 다른 대답이 있습니다.) 예를 들어 완벽하게 할 수 있습니다.

    #!/bin/bash
    export PATH=${PREPENDPATH:?}:$PATH
    exec python "[email protected]"
    
    

    이것은 $PREPENDPATH 를 주장한다  환경에서 비어 있지 않은 문자열로 설정된 다음 $PATH 앞에 추가합니다. 새 PATH 설정을 내 보냅니다. 그런 다음 새로운 PATH를 사용하여 python 를 실행합니다.  관련 논증으로 프로그램하십시오. 와이즈 비즈  쉘 스크립트를 exec 로 대체 . 이것은 다음과 상당히 다릅니다.

    python
    
    

    표상 적으로도 마찬가지입니다. 그러나 이것은 #!/bin/bash PATH=${PREPENDPATH:?}:$PATH exec python "[email protected]" 를 실행합니다  프로세스 환경에서 새로운 PATH 값이 있더라도 기존 PATH에서 찾을 수 있습니다. 따라서이 예에서는 python 에서 Python을 실행하게됩니다.   /usr/bin 가 아닌 .

    여러분의 상황에서는 아마도 /home/pi/prepend/bin 를 사용하지 않을 것입니다  명시 적 내보내기와 함께 적절한 스크립트 변형을 사용하면됩니다.

    와이즈 비즈  명령은 나머지 명령과 옵션을 구분하기 위해 이중 대시를 인식하지 않기 때문에 비정상적입니다. 이는 많은 옵션을 취하지 않기 때문이며, ENVVAR = 값 옵션이 이중 대시 앞 또는 뒤에 올 것인지 확실하지 않기 때문입니다.

    실제로 (서로 다른 버전의) 데이터베이스 서버를 실행하기위한 일련의 스크립트가 있습니다. 이 스크립트는 실제로 env 를 사용합니다  (그리고 자체 개발 한 프로그램) 서버 환경을 제어합니다 :

    env
    
    

  • 답변 # 2

    세방에 관한 위키 백과 기사를주의 깊게 읽어야합니다.

    시스템이 shebang에 해당하는 매직 넘버를 볼 때 env  shebang 다음에 주어진 경로에서 스크립트 자체를 인수로 제공합니다.

    주어진 파일 ( #!/bin/ksh # # @(#)$Id: boot.black_19.sh,v 1.3 2008/06/25 15:44:44 jleffler Exp $ # # Boot server black_19 - IDS 11.50.FC1 IXD=/usr/informix/11.50.FC1 IXS=black_19 cd $IXD || exit 1 IXF=$IXD/do.not.start.$IXS if [ -f $IXF ] then echo "$0: will not start server $IXS because file $IXF exists" 1>&2 exit 1 fi ONINIT=$IXD/bin/oninit.$IXS if [ ! -f $ONINIT ] then ONINIT=$IXD/bin/oninit fi tmpdir=$IXD/tmp DAEMONIZE=/work1/jleffler/bin/daemonize stdout=$tmpdir/$IXS.stdout stderr=$tmpdir/$IXS.stderr if [ ! -d $tmpdir ] then asroot -u informix -g informix -C -- mkdir -p $tmpdir fi # Specialized programs carried to extremes: # * asroot sets UID and GID values and then executes # * env, which sets the environment precisely and then executes # * daemonize, which makes the process into a daemon and then executes # * oninit, which is what we really wanted to run in the first place! # NB: daemonize defaults stdin to /dev/null and could set umask but # oninit dinks with it all the time so there is no real point. # NB: daemonize should not be necessary, but oninit doesn't close its # controlling terminal and therefore causes cron-jobs that restart # it to hang, and interactive shells that started it to hang, and # tracing programs. # ??? Anyone want to integrate truss into this sequence? asroot -u informix -g informix -C -a dbaao -a dbsso -- \ env -i HOME=$IXD \ INFORMIXDIR=$IXD \ INFORMIXSERVER=$IXS \ INFORMIXCONCSMCFG=$IXD/etc/concsm.$IXS \ IFX_LISTEN_TIMEOUT=3 \ ONCONFIG=onconfig.$IXS \ PATH=/usr/bin:$IXD/bin \ SHELL=/usr/bin/ksh \ TZ=UTC0 \ $DAEMONIZE -act -d $IXD -o $stdout -e $stderr -- \ $ONINIT "[email protected]" case "$*" in (*v*) track-oninit-v $stdout;; esac ) 때문에 스크립트가 실패합니다 )는실행 파일이 아니라 shebang으로 시작합니다 ....

    이상적으로, 당신은 그것을 사용하여 해결할 수 있습니다 ... execve  이 줄을 shebang으로 사용하여 스크립트에서 :

    /usr/bin/env.1
    
    

    " env 를 다루므로 리눅스에서는 작동하지 않습니다. "를 경로로 사용합니다 (인수를 나누지 않습니다)

    그래서 내가 볼 수있는 유일한 방법은 당신의 #!/usr/bin/env /usr/bin/env.1 python 를 쓰는 것입니다.  C에서

    편집 : 아무도 나를 믿지 않는 것 같습니다 ^^ 그래서 간단하고 더러운 /usr/bin/env.1 python 를 작성했습니다 :

    env.1
    
    

    env.1.c

관련 자료

  • 이전 xamarin.ios - MonoDroid 및 MonoTouch의 휴대용 클래스 라이브러리 어셈블리 참조 문제
  • 다음 크로스 플랫폼 Net?