환경 변수를 설정하는 가장 좋은 배포 / 쉘 불가지론 적 방법은 무엇입니까?


31

문제는 모든 것을 말합니다. 나는 현재 아치 리눅스와 zsh를 사용하고 있지만 (최소한) VT와 xterm 모두에서 작동하고 배포판이나 셸을 전환해도 (바람직하게는 바람직하게는) 계속 작동하는 솔루션을 원합니다.

다른 배포판 문서 에서이 질문에 대한 격렬한 이질적인 답변을 들었습니다. 우분투는 ".pam_environment 사용"이라고 말합니다. 나는 아치에서 그들이 추천하는 것이 껍질에 달려 있다고 생각합니다. 현재 모든 것을 .profile에 넣고 쉘이 어떤 이유로 소스를 제공하지 않으면 (예 : .bash_profile이있는 경우 bash) 수동으로 소싱하여 재정의합니다. 그러나 더 좋은 방법이 있어야합니다.


2
이것은 배포판과 관련이 없으며 쉘과 관련이 있습니다. 그러나 이식 가능한 방법이 있는지 확실하지 않습니다.
Joseph R.

흠. 대단 합니다.
strugee

답변:


29

불행히도 환경 변수를 설정하기에 완전히 이식 가능한 위치는 없습니다. 가장 가까운 두 파일 ~/.profile은 전통적인 위치이며 많은 설정에서 즉시 사용할 수 ~/.pam_environment있으며 현대적이고 평범하지만 제한적인 대안입니다.

무엇을 넣을 까 ~/.pam_environment

PAM~/.pam_environment 을 사용 하고이 파일을 활성화 한 모든 로그인 방법으로 파일 을 읽습니다 . 오늘날 대부분의 Linux 시스템에 적용됩니다.

가장 큰 장점은 ~/.pam_environment사용자의 셸이 시작되기 전에 (활성화 된 경우) 읽히므로 세션 유형, 로그인 셸 및 기타 복잡성에 관계없이 작동한다는 것입니다. 심지어 같은 비 대화 형 로그인 작동 su -c somecommand하고 ssh somecommand.

주요 제한 사항은 ~/.pam_environment복잡한 쉘 구문이 아닌 간단한 할당 만 할 수 있다는 것입니다. 이 파일의 구문은 다음과 같습니다.

  • 파일은 한 줄씩 구문 분석됩니다.
  • 선행 공백은 무시됩니다.
  • 선택적으로 줄과 export단일 공백 으로 시작할 수 있습니다 (탭이 아닌 그림으로 이동).
  • 그런 다음 각 줄은 VAR=VALUEVAR이 문자, 숫자 및 밑줄로 구성된 형식이어야합니다 .
  • # 주석을 시작하면 값으로 표시 될 수 없습니다.
  • VALUE로 시작 '하거나 "다른 동일한 따옴표가 포함 된 경우 VAR은 따옴표 사이의 문자열로 설정됩니다 (두 번째 따옴표 뒤의 모든 항목은 무시 됨). 그렇지 않으면 =부호 뒤에 VAR이 문자열로 설정됩니다 .
  • 이 없으면 =변수가 환경에서 제거됩니다.

따라서 거꾸로 ~/.pam_environment다양한 상황에서 작동합니다. 단점은 다른 변수를 기반으로 변수의 값을 설정하거나 (예 : PATH에 디렉토리 추가) 명령의 출력을 사용하는 등의 동적 설정을 가질 수 없으며 (예 : 디렉토리 또는 프로그램이 존재하는지 테스트) 문자 ( #'", 개행)는 값을 입력하는 것이 불가능하거나 번거 롭습니다.

무엇을 넣을 까 ~/.profile

이 파일에는 이식 가능 (POSIX) sh 구문이 있어야합니다. [[ … ]]시스템에 이러한 쉘이있는 것으로 알고있는 경우 ksh 또는 bash 확장 (배열 등) 만 사용 하십시오 /bin/sh.

이 파일은 자동화 된 응용 프로그램에서 스크립트로 읽을 수 있으므로 출력을 생성하거나 호출하는 프로그램을 호출해서는 안됩니다 exec. 텍스트 모드 로그인에서이를 수행하려면 대화식 쉘에 대해서만 수행하십시오. 예:

case $- in *i*)
  # Display a message if I have new mail
  if mail -e; then echo 'You have new mail'; fi
  # If zsh is available, and this looks like a text-mode login, run zsh
  case "`ps $PPID` " in
    *" login "*)
      if type zsh >/dev/null 2>/dev/null; then exec zsh; fi;;
  esac
esac

이것은 /bin/sh로그인 쉘로 사용하고 선호하는 쉘로 전환 하는 예입니다 . 내 sysadmin이 변경을 거부 할 때 bash를 로그인 쉘로 사용하는 방법 도 참조하십시오.

~/.profile비 그래픽 로그인에서 읽을 수없는 경우 는 언제 입니까?

다른 로그인 쉘 은 다른 파일을 읽습니다.

로그인 쉘이 bash 인 경우

Bash는 읽 ~/.bash_login거나 ~/.bash_profile대신에 존재합니다 ~/.profile. 또한 bash ~/.bashrc는 대화식 인 경우에도 로그인 쉘에서 읽지 않습니다 . 이 단점을 다시 기억하지 않으려면 ~/.bash_profile다음 두 줄로를 만드십시오 .

. ~/.profile
case $- in *i*) . ~/.bashrc;; esac

참조 어떤 설정 파일의 bash와 환경 변수를 설정하는 데 사용되어야 하는가?

로그인 쉘이 zsh 인 경우

zsh을 읽기 ~/.zprofile~/.zlogin있지만 ~/.profile. Zsh는 sh와 다른 구문을 사용하지만 ~/.profilesh 에뮬레이션 모드에서 읽을 수 있습니다 . 당신은 이것을 위해 사용할 수 있습니다 ~/.zprofile:

emulate sh -c '. ~/.profile'

Zsh가 ~ / .profile을 누르지 않음을 참조하십시오.

로그인 쉘이 다른 쉘인 경우

/bin/sh로그인 셸로 사용하고 즐겨 사용하는 셸 (예 : 물고기)을 대화식 셸로만 사용하면 부족한 일이 없습니다 . 그것이 zsh로하는 일입니다. 에서 다른 쉘을 호출하는 예는 위를 참조하십시오 ~/.profile.

원격 명령

대화식 쉘을 거치지 않고 원격 명령을 호출 할 때 모든 쉘이 시작 파일을 읽는 것은 아닙니다.

Ksh는 ENV변수가 전달한 경우 변수로 지정된 파일을 읽습니다 .

Bash ~/.bashrc대화식아니고 (!) 상위 프로세스가 rshd또는 인 경우 Bash를 읽습니다 sshd. 그래서 당신 ~/.bashrc과 함께 시작할 수 있습니다

if [[ $- != *i* ]]; then
  . ~/.profile
  return
fi

Zsh는 ~/.zshenv시작할 때 항상 읽습니다 . 다른 변수를 설정 한 서브 쉘 인 경우에도 zsh의 모든 단일 인스턴스에서 읽으므로주의해서 사용하십시오. zsh을 당신의 로그인 쉘이고 당신 만 원격 명령에 대한 일련의 변수를 사용 가드 사용하고자하는 경우에 설정 몇 가지 변수 ~/.profile, 등을 MY_ENVIRONMENT_HAS_BEEN_SET=yes, 그리고 읽기 전에이 가드를 확인 ~/.profile.

if [[ -z $MY_ENVIRONMENT_HAS_BEEN_SET ]]; then emulate sh -c '~/.profile'; fi

그래픽 로그인의 경우

많은 배포판, 디스플레이 관리자 및 데스크탑 환경 ~/.profile은 시작 스크립트에서 명시 적으로 소싱하거나 로그인 셸 을 실행하여 실행되도록 정렬합니다 .

불행히도, ~/.profile읽을 수없는 곳에서 distro / DM / DE 조합을 처리하는 일반적인 방법 은 없습니다.

로 시작한 기존 세션을 사용하는 경우 ~/.xsession환경 변수를 설정해야합니다. 소싱 ~/.profile(즉 . ~/.profile) 하여 수행하십시오 . 일부 설정에서는 데스크탑 환경 시작 스크립트가 ~/.profile다시 소스로 제공 됩니다.


무엇을 case $- in *i*)합니까?
qodeninja

2
@qodeninja 패턴과 일치하는 경우 (예 : 포함 된 경우) , 즉 셸이 대화 형인 경우 다음 명령을 실행합니다 (일치 할 때까지 ;;또는 esac) . $-*i*$-i
Gilles 'SO- 악마 그만해'

$-현재 설정된 쉘 옵션의 문자열입니다. (처럼 set -x). i대화식 쉘을 의미합니다.
Peter Cordes

~/.config/env에뮬레이션 없이도 공통 파일을 소싱 할 수 없습니까 ?
Kevin Suttle

1
@ StéphaneChazelas 그것은 순수한 견해입니다. 나는 .profile상당히 오래된 Bourne 쉘을 준수하지만 일부 사람들은 신경 쓰지 않는다는 것을 알고 있습니다. 나는 자신의 파일에 대해 sh = bash라고 가정하는 사람들을 반대하지 않으며, #!/bin/shbash 기능을 사용하는 스크립트를 게시하는 경우에만 관심이 있습니다.
Gilles 'SO- 악마 그만해'

4

내가 아는 한 환경 변수를 설정하는 방법은 배포판 및 셸과 무관 한 표준이 없습니다.

가장 일반적이고 사실상의 표준은 /etc/profileand 인 것 같습니다 ~/.profile. 두 번째로 가장 흔한 것은 /etc/environmentand ~/.pam_environment입니다.

내가 찾은 모든 문서도 이미 찾은 것 같습니다. 어쨌든 다른 독자들을 위해 여기에 나열합니다.

  • 데비안은 /etc/profile~/.profile( 링크 )를 권장 합니다.
  • 우분투 권장 /etc/environment하고 ~/.pam_environment( 링크 ).
  • 아치 리눅스는 다른 사람의 사이에서, 언급, /etc/profile그리고 /etc/environment( 링크 ).

보너스 : /etc/environment데비안에서 의 사용 및 / 또는 오용을 묻는 텍스트 ( link , last update 2008).


사용하는 파일에 관계없이 여전히 다른 쉘 사이에서 호환되지 않는 구문으로 충돌합니다.
Joseph R.

1
@JosephR. 대부분의 쉘이 이전 버전과의 호환성을 유지하지는 sh않습니까? 당신이 POSIX를 고수하는 한, 나는 당신이 괜찮을 것이라고 생각했을 것입니다 ...
evilsoup

1
AFAIK cshPOSIX 방식으로 친구 나 변수에 변수를 할당 할 수 없습니다 ( set또는 비슷한 것이 필요합니다 setenv)
Joseph R.

0

~ / bin / agnostic_setenv 스크립트를 추가했습니다 :

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]="
   exit 0
endif

if ($#args == 2) then
   if ("$args[1]" =~ *csh*) then 
      echo "setenv $args[2]"
      exit 0
   else
      echo "export $args[1]=$args[2]"
      exit 0
   endif
endif

echo "setenv $args[2] $args[3]"

그리고 ~ / .perl-homedir에서 다음을 사용합니다.

eval `${HOME}/bin/agnostic_setenv $shell PERL_HOMEDIR 0`

agnostic_unsetenv에 대한 비슷한 스크립트 :

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]"
   exit 0
endif

echo "unsetenv $args[2]"
exit 0
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.