쉘 스크립트가 호출 쉘의 환경 변수를 설정할 수 있습니까? [복제]
이 질문에는 이미 답변이 있습니다.
실행할 때 호출자의 셸에 설정된 상태로 유지되는 환경 변수를 설정하는 셸 스크립트를 작성하려고합니다.
setenv FOO foo
csh / tcsh에서 또는
export FOO=foo
sh / bash에서는 스크립트 실행 중에 만 설정합니다.
나는 이미 그것을 알고있다
source myscript
새 셸을 시작하지 않고 스크립트 명령을 실행하면 "호출자"환경이 설정 될 수 있습니다.
그러나 여기 문지름이 있습니다.
이 스크립트를 bash 또는 csh에서 호출 할 수 있기를 바랍니다. 다시 말해, 어느 쉘 사용자라도 스크립트를 실행할 수 있고 쉘 환경이 변경되기를 원합니다. csh를 실행하는 사용자는 bash 스크립트를 소싱 할 수없고 bash를 실행하는 사용자는 csh 스크립트를 소싱 할 수 없으므로 'source'는 작동하지 않습니다.
스크립트에서 두 가지 버전을 작성하고 유지 관리 할 필요가없는 합리적인 솔루션이 있습니까?
셸 프로세스에는 부모 환경의 복사본이 있으며 부모 프로세스 환경에 액세스 할 수 없습니다. 쉘 프로세스가 종료되면 환경에 대한 변경 사항이 유실됩니다. 쉘 환경을 구성하기 위해 스크립트 파일을 소싱하는 것이 가장 일반적으로 사용되는 방법입니다. 글 머리 기호를 물고 두 가지 유형의 쉘 각각에 대해 하나씩 유지하는 것이 좋습니다.
"dot space script"호출 구문을 사용하십시오. 예를 들어 다음은 스크립트의 전체 경로를 사용하여 수행하는 방법입니다.
. /path/to/set_env_vars.sh
다음은 스크립트와 동일한 디렉토리에있는 경우 수행 방법입니다.
. set_env_vars.sh
이들은 다른 쉘을로드하는 대신 현재 쉘에서 스크립트를 실행합니다 (이 경우 수행됩니다 ./set_env_vars.sh
). 동일한 쉘에서 실행되므로 설정 한 환경 변수는 종료 될 때 사용할 수 있습니다.
이것은 호출하는 것과 동일 source set_env_vars.sh
하지만 입력하는 것이 더 짧으며 입력 source
하지 않는 곳에서는 작동 할 수 있습니다 .
호출자의 쉘이 다른 프로세스 컨텍스트에 있기 때문에 호출자의 쉘을 수정할 수 없습니다. 자식 프로세스가 셸 변수를 상속하면 복사본 자체를 상속합니다.
tcsh 또는 sh에 대한 올바른 명령을 실행하는 스크립트를 작성하는 방법에 따라 스크립트를 작성하는 것이 가능합니다. 스크립트가 "setit"이라면 다음을 수행하십시오.
ln -s setit setit-sh
과
ln -s setit setit-csh
이제 직접 또는 별칭으로 sh에서이 작업을 수행합니다.
eval `setit-sh`
또는 이것은 csh에서
eval `setit-csh`
setit은 $ 0을 사용하여 출력 스타일을 결정합니다.
이것은 사람들이 TERM 환경 변수 세트를 얻는 데 사용하는 방법을 보여줍니다.
여기서 장점은 setit이 원하는 쉘로 작성되었다는 것입니다.
#!/bin/bash
arg0=$0
arg0=${arg0##*/}
for nv in \
NAME1=VALUE1 \
NAME2=VALUE2
do
if [ x$arg0 = xsetit-sh ]; then
echo 'export '$nv' ;'
elif [ x$arg0 = xsetit-csh ]; then
echo 'setenv '${nv%%=*}' '${nv##*=}' ;'
fi
done
위에서 주어진 심볼릭 링크와 역 인용 식의 평가를 사용하면 원하는 결과를 얻을 수 있습니다.
csh, tcsh 또는 유사한 쉘에 대한 호출을 단순화하려면 다음을 수행하십시오.
alias dosetit 'eval `setit-csh`'
또는 sh, bash 등의 경우 :
alias dosetit='eval `setit-sh`'
이것에 대한 한 가지 좋은 점은 목록을 한 곳에만 유지하면된다는 것입니다. 이론적으로는 목록에 파일을 넣고 cat nvpairfilename
"in"과 "do"사이에 둘 수도 있습니다.
이것은 로그인 쉘 터미널 설정이 수행되는 방식과 거의 비슷합니다. 스크립트는 로그인 쉘에서 실행되는 통계를 출력합니다. 별명은 일반적으로 "tset vt100"과 같이 호출을 단순하게 만드는 데 사용됩니다. 다른 답변에서 언급했듯이 INN UseNet 뉴스 서버에도 비슷한 기능이 있습니다.
내 .bash_profile에는 다음이 있습니다.
# No Proxy
function noproxy
{
/usr/local/sbin/noproxy #turn off proxy server
unset http_proxy HTTP_PROXY https_proxy HTTPs_PROXY
}
# Proxy
function setproxy
{
sh /usr/local/sbin/proxyon #turn on proxy server
http_proxy=http://127.0.0.1:8118/
HTTP_PROXY=$http_proxy
https_proxy=$http_proxy
HTTPS_PROXY=$https_proxy
export http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
}
따라서 프록시를 비활성화하려면 함수가 로그인 셸에서 실행되고 변수를 예상대로 설정합니다.
gdb와 setenv (3) 을 사용하면 "종류"가 가능 하지만 실제로이 작업을 수행하는 것은 쉽지 않습니다. (또한 가장 최근의 우분투는 커널이 ptrace에 대해 더 관대 한 것을 말하지 않고 실제로 이것을 할 수 없으며 다른 배포판에도 마찬가지입니다.)
$ cat setfoo
#! /bin/bash
gdb /proc/${PPID}/exe ${PPID} <<END >/dev/null
call setenv("foo", "bar", 0)
END
$ echo $foo
$ ./setfoo
$ echo $foo
bar
이것은 작동합니다. 제가 사용하는 것이 아니지만 '작동'합니다. teredo
환경 변수를 설정 하는 스크립트 를 만들어 봅시다 TEREDO_WORMS
:
#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL -i
Korn 쉘에서 해석하고 환경 변수를 내 보낸 다음 새로운 대화식 쉘로 대체합니다.
이 스크립트를 실행하기 전에 SHELL
환경에서 C 쉘로 TEREDO_WORMS
설정 했으며 환경 변수 가 설정되지 않았습니다.
% env | grep SHELL
SHELL=/bin/csh
% env | grep TEREDO
%
스크립트가 실행되면 다른 대화식 C 쉘인 새 쉘에 있지만 환경 변수가 설정됩니다.
% teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%
이 쉘을 종료하면 원래 쉘이 다음을 대신합니다.
% exit
% env | grep TEREDO
%
환경 변수는 원래 쉘 환경에서 설정되지 않았습니다. exec teredo
명령을 실행하는 데 사용 하는 경우 원래 대화식 쉘은 환경을 설정하는 Korn 쉘로 교체 된 다음 새로운 대화식 C 쉘로 교체됩니다.
% exec teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%
exit
(또는 Control-D) 를 입력하면 셸이 종료되고 해당 창에서 로그 아웃되거나 실험이 시작된 이전 레벨의 셸로 되돌아갑니다.
Bash 또는 Korn 쉘에서도 동일한 메커니즘이 작동합니다. 종료 명령 후 프롬프트가 재미있는 위치에 나타날 수 있습니다.
주석의 토론에 유의하십시오. 이것은 내가 권장하는 솔루션은 아니지만 모든 쉘에서 작동하는 환경을 설정 -i
하는 대화식 쉘 작성 옵션을 허용하는 단일 스크립트의 명시된 목적을 달성합니다 . 당신은 또한 추가 할 수 있습니다 "$@"
후 일반으로 쉘 가능한을 '설정 환경과 명령을 실행'도구를 수있는 다른 인수를 중계 할 수있는 옵션 후. -i
다른 인수가 있으면를 생략하여 다음을 수행 할 수 있습니다 .
#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL "${@-'-i'}"
"${@-'-i'}"
인수리스트가 적어도 하나 개의 인자를 포함하는 경우, 원래의 인수 목록을 사용하여 비트 수단 '; 그렇지 않으면 -i
존재하지 않는 인수를 대체 하십시오.
모듈을 사용해야합니다 ( http://modules.sourceforge.net/ 참조) .
편집 : 모듈 패키지는 2012 년 이후 업데이트되지 않았지만 여전히 기본 사항에 대해서는 정상적으로 작동합니다. 모든 새로운 기능, 종소리 및 휘파람은 오늘 lmod에서 발생합니다 (나는 그것을 더 좋아합니다) : https://www.tacc.utexas.edu/research-development/tacc-projects/lmod
내가 언급하지 않은 또 다른 해결 방법은 변수 값을 파일에 쓰는 것입니다.
나는 모든 테스트 대신 마지막 세트 테스트를 실행하고 싶었던 매우 비슷한 문제에 부딪쳤다. 첫 번째 계획은 env 변수 TESTCASE를 설정하기위한 하나의 명령을 작성한 다음이를 사용하여 테스트를 실행하는 다른 명령을 사용하는 것입니다. 말할 것도없이 당신과 똑같은 문제가있었습니다.
그러나이 간단한 해킹을 생각해 냈습니다.
첫 번째 명령 ( testset
) :
#!/bin/bash
if [ $# -eq 1 ]
then
echo $1 > ~/.TESTCASE
echo "TESTCASE has been set to: $1"
else
echo "Come again?"
fi
두 번째 명령 ( testrun
) :
#!/bin/bash
TESTCASE=$(cat ~/.TESTCASE)
drush test-run $TESTCASE
bash 스크립트 위에 -l 플래그를 추가하십시오.
#!/usr/bin/env bash -l
...
export NAME1="VALUE1"
export NAME2="VALUE2"
NAME1
및 의 값이 NAME2
현재 환경으로 내보내졌지만 이러한 변경 사항은 영구적이지 않습니다. 영구적으로 유지하려면 .bashrc
파일 또는 다른 init 파일 에 추가해야 합니다.
매뉴얼 페이지에서 :
-l Make bash act as if it had been invoked as a login shell (see INVOCATION below).
하위 프로세스에 환경 변수를 인쇄하도록 지시하고 ( "env"호출), 상위 프로세스에서 인쇄 된 환경 변수를 반복하고 해당 변수에 대해 "내보내기"를 호출 할 수 있습니다.
다음 코드는 find 출력 캡처를 기반으로 합니다. bash 배열로 -print0
부모 쉘이 bash라면
while IFS= read -r -d $'\0' line; do
export "$line"
done < <(bash -s <<< 'export VARNAME=something; env -0')
echo $VARNAME
상위 쉘이 대시이면 read
-d 플래그를 제공하지 않고 코드가 더 복잡해집니다.
TMPDIR=$(mktemp -d)
mkfifo $TMPDIR/fifo
(bash -s << "EOF"
export VARNAME=something
while IFS= read -r -d $'\0' line; do
echo $(printf '%q' "$line")
done < <(env -0)
EOF
) > $TMPDIR/fifo &
while read -r line; do export "$(eval echo $line)"; done < $TMPDIR/fifo
rm -r $TMPDIR
echo $VARNAME
bash_profile이 다른 다른 Bash를 호출 할 수 있습니다. 또한 다중 bashprofile 환경에서 사용하기 위해 특수한 bash_profile을 작성할 수 있습니다.
당신이 사용할 수있는 기억 기능을 bashprofile의 내부 및 기능에 avialable 전 세계적으로 될 것입니다. 예를 들어, "함수 사용자 {export USER_NAME $ 1}"은 (는) 런타임에서 변수를 설정할 수 있습니다. grep olegchir
기술적으로는 맞습니다. 'eval'만 다른 쉘을 포크하지 않습니다. 그러나 수정 된 환경에서 실행하려는 응용 프로그램의 관점에서 차이는 없습니다. 자식이 부모의 환경을 상속하므로 (수정 된) 환경은 모든 내림차순 프로세스로 전달됩니다.
실제로, 부모 프로그램 / 쉘에서 실행되는 한 변경된 환경 변수 '스틱'.
상위 (Perl 또는 쉘)가 종료 된 후에 환경 변수가 남아 있어야하는 경우, 상위 쉘이 무거운 리프팅을 수행해야합니다. 문서에서 본 한 가지 방법은 현재 스크립트가 필요한 '내보내기'언어로 실행 파일을 생성 한 다음 부모 셸이이를 실행하도록 속이는 것입니다. 비 휘발성 버전의 수정 된 환경을 남겨 두려는 경우 'source'명령을 사용하십시오. 최선의 Kluge.
두 번째 방법은 수정 된 매개 변수를 포함하도록 셸 환경 (.bashrc 등)을 시작하는 스크립트를 수정하는 것입니다. 초기화 스크립트를 연결하면 다음에 시작할 때 쉘을 사용하지 못할 수 있습니다. 현재 쉘을 수정하기위한 많은 도구가 있습니다. 필요한 조정을 '런처'에 첨부함으로써 이러한 변경 사항을 효과적으로 추진할 수 있습니다. 일반적으로 좋은 생각은 아닙니다. 특정 응용 프로그램 제품군에 대한 환경 변경 만 필요한 경우에는 나중에 돌아가서 셸 시작 스크립트를 원래 상태 (vi 또는 기타 사용)로 되돌려 야합니다.
간단히 말해서, 좋은 방법은 없습니다. 아마도 이것은 시스템의 보안이 결정적으로 손상되지 않도록하기 위해 어려워졌습니다.
짧은 대답은 아니요, 부모 프로세스의 환경을 변경할 수는 없지만 사용자가 선택한 환경 변수 및 사용자 정의 환경 변수가있는 환경 인 것 같습니다.
그렇다면 왜 단순히
#!/usr/bin/env bash
FOO=foo $SHELL
그런 다음 환경을 다 마치면 exit
.
항상 별칭을 사용할 수 있습니다
alias your_env='source ~/scripts/your_env.sh'
또 다른 옵션은 "환경 모듈"( http://modules.sourceforge.net/ )을 사용하는 것입니다. 불행히도 이것은 혼합에 제 3의 언어를 도입합니다. Tcl 언어로 환경을 정의하지만 일반적인 수정 (접두사 대 추가 대 세트)에 대한 몇 가지 편리한 명령이 있습니다. 또한 환경 모듈이 설치되어 있어야합니다. 그런 다음 module load *XXX*
원하는 환경 이름을 지정할 수 있습니다 . 모듈 명령은 기본적으로 eval
Thomas Kammeyer가 위에서 설명한 메커니즘 의 멋진 별칭입니다 . 여기서 주요 장점은 환경을 한 언어로 유지하고 "환경 모듈"을 사용하여 sh, ksh, bash, csh, tcsh, zsh, python (?!? !!) 등으로 변환 할 수 있다는 것입니다.
나는 몇 년 전에 이것을했습니다. 올바르게 기억한다면, 각 .bashrc 및 .cshrc에 별명을 매개 변수와 함께 포함시켜 환경을 공통 양식으로 설정하는 각 양식의 별명을 지정했습니다.
그런 다음 두 쉘 중 하나에서 소스를 생성하는 스크립트에는 마지막 양식의 명령이 있으며, 각 쉘에서 별명을 지정합니다.
구체적인 별칭을 찾으면 게시합니다.
파이프, 평가 및 신호를 사용하여 솔루션을 만들었습니다.
parent() {
if [ -z "$G_EVAL_FD" ]; then
die 1 "Rode primeiro parent_setup no processo pai"
fi
if [ $(ppid) = "$$" ]; then
"$@"
else
kill -SIGUSR1 $$
echo "$@">&$G_EVAL_FD
fi
}
parent_setup() {
G_EVAL_FD=99
tempfile=$(mktemp -u)
mkfifo "$tempfile"
eval "exec $G_EVAL_FD<>'$tempfile'"
rm -f "$tempfile"
trap "read CMD <&$G_EVAL_FD; eval \"\$CMD\"" USR1
}
parent_setup #on parent shell context
( A=1 ); echo $A # prints nothing
( parent A=1 ); echo $A # prints 1
모든 명령에서 작동 할 수 있습니다.
OS X bash에서 다음을 수행 할 수 있습니다
. bash 스크립트 파일을 작성하여 변수를 설정 해제하십시오.
#!/bin/bash
unset http_proxy
파일을 실행 가능하게 만들기
sudo chmod 744 unsetvar
별칭 만들기
alias unsetvar='source /your/path/to/the/script/unsetvar'
스크립트 파일이 포함 된 폴더가 경로에 추가 된 상태에서 사용할 준비가되어 있어야합니다.
협력 프로세스 로이 문제를 해결하는 방법을 문서화 한 답변이 없습니다. 이와 같은 일반적인 패턴 ssh-agent
은 자식 프로세스가 부모가 할 수있는 표현식을 인쇄하도록하는 것 eval
입니다.
bash$ eval $(shh-agent)
예를 들어 ssh-agent
Csh 또는 Bourne 호환 출력 구문을 선택하는 옵션이 있습니다.
bash$ ssh-agent
SSH2_AUTH_SOCK=/tmp/ssh-era/ssh2-10690-agent; export SSH2_AUTH_SOCK;
SSH2_AGENT_PID=10691; export SSH2_AGENT_PID;
echo Agent pid 10691;
(이로 인해 에이전트 실행이 시작되지만이 출력을 셸 프롬프트에 복사하여 붙여 넣지 않으면 실제로 사용할 수 없습니다.) 비교 :
bash$ ssh-agent -c
setenv SSH2_AUTH_SOCK /tmp/ssh-era/ssh2-10751-agent;
setenv SSH2_AGENT_PID 10752;
echo Agent pid 10752;
(당신이 볼 수 있듯이 csh
및 tcsh
사용 setenv
설정 varibles에 있습니다.)
자신의 프로그램도이 작업을 수행 할 수 있습니다.
bash$ foo=$(makefoo)
귀하의 makefoo
스크립트는 단순히 계산하고 값을 출력하고, 호출자가 무엇이든 그들이 그것으로 싶어 할 것 - 일반적인 사용 사례입니다 변수에 할당하지만, 아마 뭔가 당신은 가치를 생산하는 도구로 하드 코드로 원하는 .
그것은 내가 뛰어난 것으로 부르지는 않지만, 어쨌든 쉘에서 스크립트를 호출 해야하는 경우에도 작동합니다. 좋은 해결책은 아니지만 단일 정적 환경 변수의 경우 충분히 잘 작동합니다.
1.) 0 (성공) 또는 1 (성공하지 않음)을 종료하는 조건으로 스크립트를 작성하십시오.
if [[ $foo == "True" ]]; then
exit 0
else
exit 1
2.) 종료 코드에 의존하는 별명을 작성하십시오.
alias='myscript.sh && export MyVariable'
스크립트를 호출하는 별명을 호출하여 조건을 평가합니다.이 조건은 상위 쉘에서 환경 변수를 설정하기 위해 '&&'를 통해 0을 종료해야합니다.
이것은 flotsam이지만 핀치에 유용 할 수 있습니다.
$ SHELL / $ TERM 설정에 따라 조건문을 작성하는 것 외에는 없습니다. 펄 사용에있어 무엇이 문제입니까? 꽤 편 재적이며 (유닉스가없는 단일 UNIX 변형을 생각할 수 없음) 문제를 해결할 것입니다.
'development' 카테고리의 다른 글
Java에서 함수를 매개 변수로 전달하는 방법은 무엇입니까? (0) | 2020.02.23 |
---|---|
DAO와 리포지토리 패턴의 차이점은 무엇입니까? (0) | 2020.02.23 |
JavaScript로 웹 페이지의 HTTP 헤더에 액세스 (0) | 2020.02.23 |
Visual Studio : 바로 가기 키 : 복제 선 (0) | 2020.02.23 |
Chrome 데스크톱 알림 예 (0) | 2020.02.23 |