쉘의 구성 파일을 가져오는 것을 피해야 할 이유가 있습니까?

쉘의 구성 파일을 가져오는 것을 피해야 할 이유가 있습니까?

나는 최근에 다음 조언이 포함된 답변을 읽었습니다.

하지만,일반적으로 말하자면, ⚠️당신은해야하지 source ~/.zshrc.도트 파일의 내용에 따라 다양한 문제가 발생할 수 있습니다.

나는 OP에게 이것이 왜 문제가 될 수 있는지에 대한 예를 물었고 다음과 같은 말을 들었습니다.

쉘이 시작될 때 이미 가져오기 때문에 명령이 실행되는 순서가 중요할 수 있습니다. 간단한 예로, 파일을 넣고 ls() { command ls -x "$@" }; alias ls='ls -AF'.zshrc을 다시 시작하면 source ~/.zshrc... 이제 오류가 발생합니다 zsh: defining function based on alias ls'. 이는 상당히 무해한 예일 뿐입니다. 상황이 더 까다로워질 수도 있습니다

오류를 재현할 수는 없지만 이는 타당해 보입니다 zsh. 그럴듯해 보이지만 이것이 심각한 문제를 일으킬 수 있는 상황은 상상하기 어렵습니다.이러한 문제는 깨끗한 새 세션을 열 때도 발생하지 않습니다.. 제가 생각할 수 있는 최악의 시나리오는 오류 메시지를 받는 것인데, 이를 구현하는 방법조차 모릅니다.

rc그렇다면 변경 사항을 현재 셸 세션으로 가져오기 위해 셸 파일을 변경한 후 수동으로 가져오는 것을 피해야 하는 타당한 이유가 있습니까 ?

나는 수년 동안 이 일을 해왔다는 것을 알고 있습니다 bash. 주기적으로 기능을 추가하거나 기능을 변경한 ~/.bashrc다음 . ~/.bashrc그것을 얻습니다. 실제로 심각한 문제를 일으킬 수 있는 상황이 있습니까? 나는 우리가 몇 가지 극단적인 사례를 찾을 수 있다고 생각하지만, 이것이 그러한 자비로운 경고를 정당화하기에 충분합니까? 어쩌면 zsh내가 사용자로서 경험하지 못한 몇 가지 특정한 상황이 있을 수 있습니까 bash?

Bourne 계열 쉘(bash, sh, zsh, ksh 등)에 대한 답변에 관심이 있습니다.

답변1

동일한 이름의 함수와 별칭을 정의하는 초기화 파일의 예( init.sh이러한 함수와 별칭 정의가 사용된다고 가정)(별칭+함수를 호출하여 시연):

foo() { echo "foo: $1"; }
alias foo='foo bar'
foo

배쉬 4.4 및 5.0:

처음으로 정의를 로드하면 정상적으로 작동합니다. 그렇다면 .bashrc쉘이 시작될 때 이런 일이 발생합니다.

$ . init.sh
foo: bar

또 다른 시도 실패:

$ . init.sh
bash: init.sh: line 1: syntax error near unexpected token `('
bash: init.sh: line 1: `foo() { echo "foo: $1"; }'

함수 이름을 인용하거나 이스케이프하는 것도 작동하지 않습니다.

$ \foo() { echo "foo: $1"; }
bash: `\foo': not a valid identifier

unalias foo먼저 들어가야 합니다 init.sh. 또는 명령줄의 첫 번째 단어가 아니기 function foo { ... }때문에 별칭을 무시하는 를 사용해야 합니다.foo

Bash는 실제로 별칭을 확장하므로 별칭이 한 단어를 다른 단어로 변경하면 정의된 함수의 이름이 변경됩니다.

$ alias foo=foobar; unset -f foo foobar
$ foo() { echo hi; }
$ typeset -p -f foo
bash: typeset: foo: not found
$ typeset -p -f foobar
foobar () 
{ 
    echo hi
}

별칭의 내용에 관계없이 현재 버전의 Zsh에서는 오류가 발생합니다.

% . ./init.sh
foo: bar
% . ./init.sh
./init.sh:1: defining function based on alias `foo'
./init.sh:1: parse error near `()'

그러나 zsh에서는 함수 이름을 인용하거나 이스케이프하는 것이 가능합니다.

그것항상 이렇지는 않아예를 들어, zsh 5.3.1에서는 함수가 (재)정의되면 별칭이 확장되고, 별칭이 여러 단어로 확장되면 자동으로 함수의 추가 복사본을 얻게 됩니다. (이것은 함수가 단 한 단어로 확장된 경우 얻을 수 있는 이름입니다.) 예를 들어 위의 첫 번째 예 별칭의 경우 및 둘 다 정의됩니다 foo.bar

% alias foo='foo bar'
% foo() { echo hi; }
% typeset -p -f foo
foo () {
        echo hi
}
% typeset -p -f bar
bar () {
        echo hi
}

물론, 동일한 이름의 함수와 별칭이 없으면 이 중 어떤 것도 발생하지 않습니다. 대신에 필요한 모든 기능을 함수에 포함할 수 있습니다(특히 함수가 어떤 면에서는 별칭보다 낫기 때문입니다).


이로 인해 심각한 문제가 발생할 수 있는 상황은 상상할 수 없습니다.

저도요.

init 스크립트의 초기 부분이 명령 A를 사용하여 잠재적으로 위험한 작업을 수행한 다음(명령 자체는 반드시 위험한 것은 아니며 특정 조건에서 사용할 수 있음) 동일한 스크립트의 후속 부분이 A를 재정의하는 경우 다음을 수행할 수 있습니다. 처음 사용할 때 함수나 별칭이 손상되면 문제가 발생합니다.

그러나 이는 다른 면에서도 취약합니다. 예를 들어, 함수 정의를 맨 위로 이동하기 위해 파일을 재구성하면 파일이 손상되어 동일한 위험한 동작이 발생합니다. 특히 함수/별칭 정의 순서에 따라 스크립트를 종속시키지 않는 것이 가장 좋습니다. 잠재적으로 위험한 명령을 실행할 때.

답변2

다음과 같은 내용이 있다고 가정해 보겠습니다 .bashrc.

foo=$(grep -m1 A /etc/os-release)
PS1="$foo %u $"
grep () { command grep -H "$@"; }

이는 프롬프트에 배포 이름을 표시하고 grep항상 파일 이름만 인쇄하는 빠른 방법입니다. 파일을 리소스로 사용하면 프롬프트에 파일 이름도 표시됩니다. 어떤 사람들은 이것이 놀라운 일이 아니라고 말할 수도 있습니다. 이제 이 줄 사이에 수십 개의 다른 셸 구성이 있다고 상상해 보세요. 어쩌면 다른 파일에도 있을 수 있으며, 이 구성은 차례로 기본 rc 파일에서 제공됩니다. (명령에 대한 별칭을 생성하는 일부 소프트웨어의 최근 예가 있었는데 env, 이로 인해 여러 가지 용도가 중단될 수 있습니다.) 그러면 어떤 문제가 발생할지 예측하기가 어려워집니다.

bashrc를 다시 얻는 것은 당신이 직접 작성하더라도 까다롭다고 말하고 싶습니다. bashrc가 충분히 길면 자체적으로 까다로운 상호 작용이 발생할 수 있습니다.

답변3

쉘 초기화가 시스템에 미치는 영향에 익숙하지 않다면 사용하지 마십시오! 정말 그렇지 않습니다. UTBLT를 하지 마세요! (도구를 배우기 전에 도구를 사용하십시오) (물건을 배우기 전에 물건을 사용하십시오).

대부분의 쉘은 -x각 명령의 실행을 표시하는 옵션을 제공합니다. man귀하의 페이지를 읽으십시오 $SHELL.

"잘 작성된" IMHO 쉘 초기화 스크립트는 환경 변수, 플래그 파일 등을 확인하여 실행되었는지 확인하고 "올바른 작업을 수행"합니다.

관련 정보