bashrc에서 [-n“$ PS1”]의 목적


10

어떤 목적을하면은 수행 [ -n "$PS1" ][ -n "$PS1" ] && source ~/.bash_profile;역할을? 이 줄은 .bashrc도트 파일 저장소에 포함되어 있습니다 .

답변:


20

이것은 쉘이 대화식인지 아닌지를 확인하는 것입니다. 이 경우, ~/.bash_profile쉘이 대화식 인 경우 에만 파일을 소싱하십시오 .

"이 셸이 대화 형입니까?"를 참조하십시오. bash 매뉴얼에는 특정 관용구가 인용되어 있습니다. 또한 $-특수 변수에 i문자 가 포함되어 있는지 테스트하여 쉘이 대화식인지 확인하는 것이 좋습니다 .이 문제에 대한 더 나은 접근 방법입니다.


쉘이 대화 형이라면 bash는 최소한 PS1과 PS2설정 해제 합니다. 을 사용 ( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )하여 간단히 인쇄 할 수 있습니다 []. 어떤 경우에는 ... 적어도 실험에서, 동일한 작업을 수행하지 않습니다 zsh을들이는 것 같다 의도 의이 [ -n "$PS1" ]쉘이 대화 형인지 여부를 확인하는 것입니다.
filbranden

3
bash비 대화식 (이전 코멘트에 오타가) 버그가 IMO입니다 설정 해제의 PS1는 PS1은 그것을 해제하기 어떤 사업이없는, 떠들썩한 특정 변수가 아닙니다. 이 작업을 수행하는 유일한 쉘입니다 ( 비대화 식인 경우에도 기본값으로 yash설정 PS1됨).
Stéphane Chazelas

1
문제의 코드는 bash 특정 파일에 있기 때문에 합리적인 답변처럼 보입니다. 다른 답변은 POSIX 사양이나 다른 쉘의 일반적인 사례를 다룹니다. 당신은“이것의 목적은 무엇입니까?”라고 대답했습니다. 나머지는 제쳐두고 질문에 대한 의도. 배쉬가 무엇을하고 있는지, 목표를 달성하는 더 좋은 방법을 아는 것도 좋은 일입니다.
Jeff Schaller

보다 신뢰할만한 대안 (예 :)을 제안하면이 답변이 더 완벽하다고 생각합니다 [[ $- = *i* ]] && source ~/.bash_profile.
Charles Duffy

@CharlesDuffy 솔직히에는 많은 문제가 있다고 생각하지 않지만 [ -n "${PS1}" ]bash 매뉴얼 $-이 쉘이 대화 형인지 여부를 확인하기 위해 검사 를 제안 / 권장한다는 것을 강조하기 위해 여전히 대답을 업데이트했습니다. 대답 이 향상되기를 바랍니다. 건배!
filbranden

19

이것이하는 일

이것은 쉘이 대화식인지 여부를 테스트하는 광범위한 방법입니다. bash에서만 작동하고 다른 쉘에서는 작동하지 않습니다. 그래서 (괜찮다면) 괜찮지 .bashrc만 작동하지 않습니다 .profile(sh로 읽히고 bash는 sh의 가능한 구현 중 하나이며 가장 일반적인 것은 아닙니다).

왜 작동합니까 (bash에서만!)

대화식 쉘은 쉘 변수PS1 를 기본 프롬프트 문자열로 설정합니다. 따라서 쉘이 대화 형 인 PS1경우 설정됩니다 (사용자가 쉘 .bashrc을 제거하지 않은 한 아직 맨 위에있을 수 없으며 .bashrc어쨌든 할 일이 어리석은 일이라고 생각할 수 있습니다).

대화는 bash에서 참입니다. bash의 비 대화식 인스턴스는 PS1시작할 때 설정되지 않습니다. 이 동작은 bash에만 적용되며 아마도 버그입니다 (왜 ? 가 bash -c '… do stuff with $var…'작동하지 않습니까?). 그러나 4.4 (내가 작성한 최신 버전)까지 모든 bash 버전 이이 작업을 수행합니다.varPS1

많은 시스템 PS1이 환경으로 내보내 집니다. 많은 다른 포탄 사용하기 때문에 그것은 나쁜 생각 PS1하지만 다른 구문 (예 : 배쉬의 프롬프트 이스케이프는 완전히 다른 zsh을의 프롬프트 탈출 ). 그러나 실제로 PS1설정되어 있는 것을 보는 것은 쉘이 대화 형이라는 신뢰할만한 지표가 아니라는 것이 널리 퍼져 있습니다. 쉘은 PS1환경에서 상속되었을 수 있습니다 .

왜 여기에 사용 되었습니까?

.bashrcbash는 시작시 대화식 일 때 읽는 파일입니다. 덜 알려진 사실은 bash도 .bashrc로그인 쉘이며 bash의 휴리스틱은 이것이 원격 세션이라고 결론을 내립니다 (bash는 부모가 rshd또는인지 확인 sshd). 두 번째 경우 PS1에는 도트 파일이 아직 실행되지 않았기 때문에 환경에서 설정 되지 않을 수 있습니다.

그러나 코드가이 정보를 사용하는 방식은 비생산적입니다.

  • 쉘이 대화식 쉘인 경우 해당 쉘 .bash_profile에서 실행됩니다 . 그러나 .bash_profile로그인 시간 스크립트입니다. 세션 당 한 번만 실행되도록 의도 된 일부 프로그램을 실행할 수 있습니다. 해당 쉘을 실행하기 전에 사용자가 의도적으로 다른 값으로 설정 한 일부 환경 변수를 대체 할 수 있습니다. .bash_profile비 로그인 셸에서 실행 하면 방해가됩니다.
  • 쉘이 비 대화식 원격 로그인 쉘이면로드되지 않습니다 .bash_profile. 그러나 이것은 로딩의 경우 .bash_profile비 대화식 로그인 쉘이 자동으로로드하지 않기 때문에 유용 할 수 /etc/profile~/.profile.

사람들이 이것을하는 이유는 GUI (일반적인 경우)를 통해 로그인하고 환경 변수 설정을 .bash_profile대신하는 사용자를위한 것 .profile입니다. 대부분의 GUI 로그인 메커니즘은 호출 .profile하지만 호출 하지는 않습니다 .bash_profile(읽기 .bash_profile에는 sh 대신 세션 시작의 일부로 bash를 실행해야 함). 이 구성을 사용하면 사용자가 터미널을 열면 환경 변수가 나타납니다. 그러나 사용자는 GUI 응용 프로그램에서 환경 변수를 얻지 못합니다. 이는 매우 일반적인 혼란의 원인입니다. 여기서 해결책은 환경 변수를 설정 하는 .profile대신 사용하는 것입니다 .bash_profile. 사이에 다리를 추가 .bashrc하고 .bash_profile그것을 해결하는 것보다 더 많은 문제를 만듭니다.

대신해야 할 일

현재 쉘이 대화 형인지 여부를 테스트하는 간단하고 이식 가능한 방법이 -i있습니다. 옵션 이 활성화되어 있는지 테스트하십시오 .

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This shell is not interactive";;
esac

이에 유용 .bashrc읽어 .profile쉘이 대화 형이 아닌 경우에만 코드가 무엇의 반대, 즉 -! 읽기 .profile배쉬는 (비 대화식) 로그인 쉘이며, 대화 형 쉘의 경우를 읽을 수없는 경우.

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

4
쉘이 대화 형인지 테스트하는 더 좋은 방법은 [[ -o interactive ]](ksh, bash, zsh) 또는 case $- in (*i*) ...; esac(POSIX)
Stéphane Chazelas

2
PS1대화식으로 실행하지 않으면 내 bash (버전 4.4.12)가 실제로 설정되지 않은 것 같습니다 . 테스트하기는 쉽습니다. bash 시작 파일 에 설정된 값 PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'PS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'인쇄하는 동안 아무 것도 인쇄하지 않습니다 $PS1(문자열 "cuckoo"는 인쇄하지 않음).
FooF

1
@ Stéphane Chazelas : POSIX는 대화식 쉘 을 $-포함 하지 않아도 i됩니다.
schily

1
Bosh는 2012 년부터 ksh와 호환되도록이 작업을 수행합니다. 변경 사항이 적용되기 전까지는 POSIX에서 필요하지 않았습니다.
schily

1
솔직히 말해서, [ -n "${PS1}" ] 잘못 전화하는 것이 너무 멀리 가고 있다고 말하고 싶습니다. 누군가가 PS1을 내보낼 때만 중단됩니다 (답변에서 나쁜 생각이라고 말하고 그 이유를 알 수 있습니다). 어쨌든 bash는 (쉘이 비대화 형인 경우 PS1과 PS2의 설정이 해제되어 있기 때문에.) 어쩌면 "감지 된"과 같은 단어를 사용하거나 접근의 "제한"에 대해 말하는 것이 더 좋을 것입니다. 나는 그것이 "잘못"이라고 생각하지 않습니다. PS1을 내보내는 데 문제 가 있다면 확실합니다! 어쨌든, 이것에 대해 자세히 설명해 주셔서 감사합니다.
filbranden

1

이 이상한 개념은 bashPOSIX 셸 클론으로 시작하지 않고 복제본으로 시작한 사실에서 비롯된 것 같습니다 Bourne Shell.

결과적으로 POSIX 대화식 동작 ( $ENV대화식 쉘이라고 함)이 나중에 추가되었으며 bash널리 알려지지 않았습니다.

유사한 동작을 허용하는 하나의 셸이 있습니다. 이것은 특정 값 csh$prompt가진 csh grant입니다 .

$prompt not set          non-interactive shell, test $?prompt.
$prompt set but == ""    .cshrc called by the which(1) command.
$prompt set and != ""    normal interactive shell.

그러나 이것은 Bourne Shell이나 POSIX shell에는 적용되지 않습니다.

POSIX 쉘의 경우 부여 된 유일한 방법은 대화식 쉘의 코드를 파일에 넣는 것입니다.

$ENV

그것은 쉘 특정 이름을 가지고 있습니다. 예를 들어

$HOME/.kshrc    for the korn shell
$HOME/.bashrc   for bash
$HOME/.mkshrc   for mksh
$HOME/.shrc     for the POSIX Bourne Shell

다른 사람들은 shell flag에 대해 언급 -i했지만 신뢰할 수있는 프로그래밍에는 사용할 수 없습니다. POSIX는 set -i작동하지 않으며 대화식 쉘 을 $-포함 하지도 않습니다 i. POSIX sh -i는 셸을 대화식 모드로 강제 실행하기 만하면 됩니다.

$PS1환경에서 변수 를 가져올 수 있으므로 비 대화식 모드에서도 값을 가질 수 있습니다. 사실 bash unsetPS1비 대화식 쉘에서이 표준에 의해 부여되지 않은 다른 어떤 쉘에 의해 수행되지 않습니다.

따라서 깨끗한 프로그래밍은 (와도 bash) 대화식 쉘 명령을 넣는 것 $HOME/.bashrc입니다.


0

나는 데비안이 무엇인지 먼저 이야기 할 것이고, 대부분 우분투는 bash를 설정합니다. 후자는 다른 시스템에 영향을 미칩니다.

쉘 시작 파일 설정에는 많은 의견이 있습니다.
나는 또한 내 의견을 가지고 있지만 올바른 설정의 기존 예를 보여 주려고 노력할 것입니다.
파일의 예를 찾기가 매우 쉽기 때문에 debuan을 사용하겠습니다.
그리고 데비안이 많이 사용되므로 설정이 잘 테스트되었습니다.

PS1이 설정되어 있는지 확인하는 목표는 무엇입니까?

쉘이 대화식인지 확인하십시오.

데비안 과 우분투 의 기본값/etc/profile (/ usr / share / base-files / profile) :

if [ "${PS1-}" ]; then
    if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then

if 's read : if 대화식 (PS1 기본 세트)이고 bash 쉘 (기본값으로 작동하지 않음 sh) 인 경우 PS1을 특정 새 것이 아닌 (기본이 아닌) PS1로 변경하십시오.

데비안기본값/etc/bash.bashrc 에는 다음이 포함됩니다.

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

대화 형이 소스를 제공하지 않으면 (나머지)

그러나 에서이 /etc/skel/.bashrc예이다 (사용하여 인터랙티브 셀 테스트를위한 정확한 방법은 $-)

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

그것은 PS1의 이유와 하나의 대안을 분명히 보여 주어야합니다.

올바른 순서

보고하는 설정은 피해야합니다.
(시스템 설정에서 () bash에 대한보다 구체적인 사용자 설정) 순서는 /etc/profile, /etc/bash.bashrc, ~/.profile그리고 마지막으로 ~/.bashrc. 이것은 ( /etc/profile루트 소유의 ) 가장 큰 효과 (및 더 많은 셸에 대한 ) 다음에 /etc/bash.bashrc( 루트가 소유 한) 뒤에 배치 되지만 배쉬에만 영향을 미칩니다. 그런 다음 개인 설정을 가져 오십시오. $HOME첫 번째는 ~/.profile대부분의 쉘 에 해당하며 bash에만 ~/.bashrc해당됩니다 (거의 거의 동일 ~/.bash_profile).

따라서 소스 입력 ~/.bashrc이 잘못 ~/.profile되었습니다. bash에 대한 특정 사용자 설정 을 더 많은 쉘에 영향을 미치는보다 일반적인 것으로 변환하고 있습니다 . 이 방법으로 수행 된 경우를 제외하고 :

# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

bash가 실행 중인지 확인하고 해당 .bashrc되는 경우 에만로드 합니다.

이것은 데비안에서 오는 업스트림 결정입니다. 이론적 근거는 여기에 설명되어 있습니다 .

사실, (또는 ) ~/.profile에서의 소싱 은 특정 유스 케이스에 이미로드되어 있어야하므로 일반적인 규칙을 다시 적용하는 것입니다. 그리고 파일 소싱이 반복 될 수 있기 때문에 좋은 말이 아닙니다. 하위 디렉토리가 상위 디렉토리를로드 할 때와 마찬가지로 디렉토리 루프입니다.~/.bash_profile~/.bashrc

그리고이 교차 소싱에서는 대화식 쉘 검사가 의미가 있습니다. 쉘이 대화식으로 ~/.bashrc로드 된 경우에만 로드되지만 차례로로드 될 수 있으며이 ~/.profile경우 대화식 쉘을 검사하는 것이 사용될 수 있습니다.

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