/usr/bin/env 에 대한 질문에 라인에는 pecularities
-
20-08-2019 - |
문제
질문:
- 무엇 커널을 할 경우 쉘 스크립트로 라인에는?
- 어떻게 커널을 알고 있는 인터프리터를 실행?
설명:
나는 최근에 작성하고 싶어 래퍼 /usr/bin/env 기 때문에 나는 CGI 환경을 허용하지 않을 설정 경로 변수를 제외하고,전 세계적으로(는 물론 sucks!).
그래서 저는 생각했죠,"좋아.자 설정 PREPENDPATH 설정 경로 에서 래퍼 env.".결과 스크립트(여기라 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:
env
모 2:
env -i HOME=$HOME PATH=$PREPENDPATH:$PATH ... command args
이 버전이 취소되는 모든 상속된 환경 변수를 및 실행 command
으로 정확하게 환경 설정에 의해는 백분율=value 옵션이 있습니다.
세 번째 모드-을 개정하는 환경에 덜 중요하기 때문에 당신이 할 수 있는 미세한 정기적(문)껍질입니다.(즉,"C"쉘을 다시 거기에 다른 질문들에 대한 답변을 설명하는 것.) 예를 들어,당신은 완벽하게 잘:
#!/bin/bash
export PATH=${PREPENDPATH:?}:$PATH
exec python "$@"
이 주장 $PREPENDPATH
로 설정하면 빈 문자열이 아 환경에서,그리고 그 앞에 추가 그것을 $PATH
, 및 수출에 새 경로를 설정합니다.그런 다음 사용하는 새로운 경로를 실행합니다 python
프로그램 관련 인수입니다.이 exec
대체 쉘 스크립트로 python
.이 매우 다르다:
#!/bin/bash
PATH=${PREPENDPATH:?}:$PATH exec python "$@"
표면적으로,이것은 동일합니다.그러나,이것이 실행됩 python
에서 찾은 기존의 경로는,이기는 하지만 새 값으로의 경로에서 프로세스의 환경입니다.그래서 예제에서,당신은 끝까지 실행하는 파이썬서 /usr/bin
고서 /home/pi/prepend/bin
.
귀하의 상황에서,나는 것 아마 사용 env
고 그냥 사는 적절한 변종의 스크립트는 명시적으로 수출합니다.
이 env
명령은 특이하기 때문에 그것을 인정하지 않을 두 번 돌진을 분리 옵션의 나머지 부분에서 명령입니다.이것은 부분하지 않기 때문에 많은 옵션,그리고 부분에 있기 때문에 명확하지 않지는 백분율=value 야 할 옵션이 올 전 또는 후 두 번 돌진합니다.
내가 실제로 시리즈의에 대한 스크립트를 실행하는(서로 다른 버전의)데이터베이스 서버입니다.이러한 스크립트를 정말 사용 env
(고 무리의 집에서 재배 프로그램)하 제어 서로가 서로의:
#!/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 "$@"
case "$*" in
(*v*) track-oninit-v $stdout;;
esac
다른 팁
Wikipedia 기사에 대해 신중하게 읽어야합니다 오두막.
시스템이 Shebang에 해당하는 마법 번호를 볼 때 execve
Shebang 이후의 주어진 경로에서 스크립트 자체를 인수로 제공합니다.
주어진 파일이기 때문에 스크립트가 실패합니다 (/usr/bin/env.1
) 아니다 실행 파일,하지만 셰 잔에 의해 시작됩니다 ....
이상적으로, 당신은 그것을 사용하여 해결할 수 있습니다 ... env
이 라인을 Shebang으로 스크립트에서 다음과 같습니다.
#!/usr/bin/env /usr/bin/env.1 python
Linux에서는 작동하지 않습니다. "/usr/bin/env.1 python
"길로 (인수를 나누지 않음)
그래서 내가 보는 유일한 방법은 env.1
c
편집 : 아무도 나를 믿지 않는 것 같습니다 ^^, 그래서 나는 단순하고 더러운 것을 썼습니다. env.1.c
:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
const char* prependpath = "/your/prepend/path/here:";
int main(int argc, char** argv){
int args_len = argc + 1;
char* args[args_len];
const char* env = "/usr/bin/env";
int i;
/* arguments: the same */
args[0] = env;
for(i=1; i<argc; i++)
args[i] = argv[i];
args[argc] = NULL;
/* environment */
char* p = getenv("PATH");
char* newpath = (char*) malloc(strlen(p)
+ strlen(prependpath));
sprintf(newpath, "%s%s", prependpath, p);
setenv("PATH", newpath, 1);
execv(env, args);
return 0;
}