결론/TLDR

결론/TLDR

내 아치 설치에는 다음 줄이 /etc/bash.bashrc있습니다 ./etc/skel/.bashrc

# If not running interactively, don't do anything
[[ $- != *i* ]] && return

데비안에는 /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

그러나 에 따르면 man bash비대화형 쉘은 다음 파일도 읽지 않습니다.

예를 들어, bash비대화형으로 실행될 때 쉘 스크립트를 실행하려면 환경에서 변수를 찾고 BASH_ENV, 해당 변수가 환경에 있으면 그 값을 확장하고, 확장된 값을 읽을 파일 이름으로 사용하고, 이름. Bash는 다음 명령이 실행된 것처럼 동작합니다. if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi그러나 변수 값은 PATH파일 이름을 검색하는 데 사용되지 않습니다.

내가 올바르게 이해했다면 *.bashrc이 파일은 해당 파일을 가리키도록 설정된 경우에만 읽혀집니다. BASH_ENV이는 우연히 일어날 수 없는 일이며, 누군가 그에 따라 변수를 명시적으로 설정한 경우에만 발생합니다.

.bashrc이는 사용자 피드를 자동으로 가져오는 스크립트를 설정하는 가능성을 깨뜨리는 것으로 보이며 BASH_ENV이는 유용할 수 있습니다. bash는 명시적으로 지시하지 않는 한 비대화식으로 실행될 때 이러한 파일을 절대 읽지 않는다는 점을 감안할 때 기본 *bashrc파일이 이를 허용하지 않는 이유는 무엇입니까?

답변1

이것은 제가 몇 주 전에 여기에 게시하려고 했던 질문입니다. 좋다테든, 나는 대화형 Bash 쉘에서만 발생한다는 것을 알고 있으므로 대화형 쉘에서 실행 중인지 확인할 .bashrc필요가 없습니다 . .bashrc혼란스럽게도,모두내가 사용하고 있는 배포판(Ubuntu, RHEL 및 Cygwin)은 현재 셸이 대화형인지 확인하기 위해 일종의 검사(테스트 $-또는 )를 수행합니다. $PS1나는 좋아하지 않는다화물 숭배 프로그래밍그래서 나는 내 것을 이해하기 시작했습니다 .bashrc.

Bash에는 원격 쉘을 위한 특별한 경우가 있습니다.

이 문제를 조사한 후 발견했습니다.원격 쉘다르게 대우받습니다. 비대화형 Bash 쉘은 일반적으로 ~/.bashrc시작 시 명령을 실행하지 않지만 쉘이 시작될 때 특별한 상황이 발생합니다.원격 쉘 데몬에 의해 호출됨:

rshdBash는 원격 쉘 데몬(보통 ) 또는 보안 쉘 데몬 에 의해 실행될 때와 같이 네트워크 연결에 연결된 표준 입력으로 실행 중인지 확인하려고 합니다 sshd. Bash가 이런 방식으로 실행 중이라고 판단하면 ~/.bashrc(파일이 존재하고 읽을 수 있는 경우)에서 명령을 읽고 실행합니다. 로 호출하면 이 작업을 수행하지 않습니다 sh. --norc옵션을 사용하여 이 동작을 억제할 수 있고 --rcfile옵션을 사용하여 다른 파일을 강제로 읽을 수 있지만 일반적으로 쉘은 이러한 옵션 rshd으로 호출되지 않거나 sshd지정이 허용되지 않습니다.

원격 시작 부분에 다음을 삽입하십시오 .bashrc. ( 또는 .bashrc에서 시작된 경우 테스트하는 동안 이 기능이 일시적으로 비활성화됩니다.).profile.bash_profile

echo bashrc
fun()
{
    echo functions work
}

다음 명령을 로컬로 실행합니다.

$ ssh remote_host 'echo $- $0'
bashrc
hBc bash
  • 아니요 i$-쉘이비대화형.
  • 소개가 없으면 쉘이 아님 -을 나타냅니다 .$0로그인 쉘.

원격으로 정의된 셸 기능 .bashrc도 실행할 수 있습니다.

$ ssh remote_host fun
bashrc
functions work

나는 ~/.bashrc그것이었다는 것을 알아차렸다.오직명령이 인수로 지정될 때 획득됩니다 ssh. 이는 의미가 있습니다: ssh일반 로그인 셸을 시작 .profile하거나 .bash_profile실행하는 데 사용되는 경우( .bashrc이러한 파일 중 하나가 명시적으로 이를 수행하는 경우에만 소스를 가져옵니다).

.bashrc(비대화형) 원격 명령을 실행할 때 소스를 사용하면 얻을 수 있는 주요 이점은 셸 기능을 실행할 수 있다는 것입니다. 그러나 일반 명령의 대부분은 .bashrc대화형 셸에서만 관련됩니다. 예를 들어 셸이 대화형이 아니면 별칭은 확장되지 않습니다.

원격 파일 전송이 실패할 수 있음

rshssh이는 대화형 로그인 셸을 시작하거나 비대화형 셸을 사용하여 명령을 실행하는 경우 일반적으로 문제가 되지 않습니다. 그러나 그것은문제가 될 수 있습니다rcp다음 과 같은 scp프로그램 의 경우sftp원격 쉘데이터를 전송하는 데 사용됩니다.

scp해당 명령을 사용할 때 원격 사용자의 기본 셸(예: Bash)이 암시적으로 시작되는 것으로 나타났습니다 . 매뉴얼 페이지에는 이에 대한 언급이 없습니다. 단지 scp데이터 전송을 위한 목적일 뿐입니다. ssh이것의 결과는 다음과 같습니다.bashrc표준 출력으로 인쇄하는 명령이 포함되어 있으면 파일 전송이 실패합니다.,예를 들어, 오류 없이 scp가 실패함.

15년 전 관련 Red Hat 버그 보고서도 참조하세요./etc/bashrc에 echo 명령이 있으면 scp가 중단됩니다.(결국 폐쇄됨 WONTFIX).

왜 실패 scp했는가sftp

SCP(보안 사본)그리고SFTP(보안 파일 전송 프로토콜)로컬 및 원격 측에는 전송되는 파일에 대한 정보를 교환하기 위한 자체 프로토콜이 있습니다. 원격 측의 예상치 못한 텍스트는 프로토콜의 일부로 (잘못) 해석되어 전송이 실패합니다. 에 따르면달팽이 책 FAQ

그러나 사람이 쉽게 읽을 수 있도록 로그인 시 텍스트 메시지를 출력하는 명령문(예 : , , 등 ) 이 서버의 시스템 또는 사용자별 셸 시작 파일( .bashrc, , 등)에 자주 발생합니다 ..profile/etc/csh.cshrc.loginfortuneecho "Hi there!"

표준 입력에 추가되면 이러한 코드는 대화형 로그인에서만 출력을 생성해야 합니다 tty. 이 테스트를 수행하지 않으면 이러한 텍스트 메시지가 속하지 않는 곳에 삽입됩니다. 이 경우 scp2/ 와 sftp사이의 프로토콜 흐름을 오염시킵니다 sftp-server.

쉘 시작 파일은 다음과 같은 이유로 관련이 있습니다.sshd 사용자를 대신하여 프로그램을 시작할 때 사용자의 셸을 사용합니다. (예: /bin/sh -c "명령"을 사용하십시오). 이는 Unix 전통이며 다음과 같은 장점이 있습니다.

  • 사용자의 공통 설정(명령 별칭, 환경 변수, umask 등)은 원격 명령이 실행될 때 적용됩니다.
  • 어떤 이유로 인해 인증이 여전히 예기치 않게 성공하는 경우 /bin/false로 설정하여 계정의 셸을 비활성화하는 일반적인 관행에 따라 소유자는 어떤 명령도 실행할 수 없습니다.

SCP 프로토콜 세부정보

SCP 작동 방식에 대한 자세한 내용에 관심이 있는 분들을 위해 다음에서 흥미로운 정보를 찾았습니다.SCP 프로토콜의 작동 방식세부정보가 포함된원격 측에서 세션 셸 프로필을 사용하여 scp를 실행할 수 있나요?:

예를 들어 원격 시스템의 셸 구성 파일에 다음을 추가하면 이런 일이 발생할 수 있습니다.

에코""

왜 그냥 멈춰있나요? 이것은 scp어떻게에서 비롯됩니다원천모드는 첫 번째 프로토콜 메시지의 승인을 기다립니다. 바이너리 0이 아니면 이를 원격 문제에 대한 알림으로 간주하고 새 줄이 도착할 때까지 더 많은 문자가 오류 메시지를 형성할 때까지 기다립니다. 첫 번째 줄 이후에 다른 줄을 인쇄하지 않기 때문에 로컬 파일이 scp루프에 갇혀 에서 차단됩니다 read(2). 한편 원격 측에서 셸 프로필이 처리된 후 scp수신자 모드가 시작되며 이 모드도 에서 차단됩니다. read(2), 데이터 전송 시작을 나타내는 이진수 0을 기다리고 있습니다.

결론/TLDR

일반 명령문의 대부분은 .bashrc대화형 셸에만 유용합니다. rsh원격 명령을 사용하거나 실행할 때는 효과가 없습니다 ssh. 대부분의 경우 쉘 변수, 별칭을 설정하고 함수를 정의할 필요가 없습니다.모든 텍스트scp또는 같은 프로그램을 사용하여 파일을 전송하는 경우 표준 출력은 매우 해로울 수 있습니다 sftp. 현재 쉘이 비대화형인지 확인한 후 종료하십시오 .bashrc.

답변2

매뉴얼 페이지에는 다음과 같은 비대화형 원격 쉘에 대한 bash소스가 언급되어 있지 않습니다..bashrc

ssh hostname command

http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1010

 COMMAND        EXECUTE BASHRC
 --------------------------------
 bash -c foo        NO
 bash foo           NO
 foo                NO
 rsh machine ls     YES (for rsh, which calls 'bash -c')
 rsh machine foo    YES (for shell started by rsh) NO (for foo!)
 echo ls | bash     NO
 login              NO
 bash               YES

http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1050

          /* If we were run by sshd or we think we were run by rshd, execute
             ~/.bashrc if we are a top-level shell. */
          if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2)
            {
              maybe_execute_file (SYS_BASHRC, 1);
              maybe_execute_file (bashrc_file, 1);

답변3

관례적으로 .bashrc이는 사용자가 셸에 대한 사용자 정의 구성을 저장하는 곳입니다.

이러한 사용자 정의 구성은 환경 변수, 별칭 및 멋진 프롬프트일 수 있습니다. 비대화형 쉘의 경우 이러한 누락된 항목은 의미가 없습니다. 또한 비대화형 셸은 다양한 상황에서 호출될 수 있으며 이러한 환경 변수가 거짓 부정 또는 보안 취약점으로 이어질 수 있는지 확실하지 않습니다.

가장 가까운 예는 다음과 같은 별칭입니다.

alias cp='cp -i'

그러면 비대화형 쉘이 영원히 정지됩니다.

.bashrc따라서 문제가 발생하지 않도록 상단에서 점검이 수행됩니다 .


쉘은 비대화형이라고 할 수 있기 때문에로그인쉘이므로 *bashrc소스를 명시적으로 차단할 필요가 없습니다.

껍질이 있을 때비대화형 로그인 쉘이라고 함, 소스인 경우 소스는 /etc/profile, 및에서 발견된 첫 번째 소스입니다.~/.bash_profile~/.bash_login~/.profile

bash가 대화형 로그인 셸로 호출되면,또는 --login 옵션을 사용하여 비대화형 쉘로 사용, 먼저 /etc/profile 파일(파일이 존재하는 경우)에서 명령을 읽고 실행합니다. 파일을 읽은 후 ~/.bash_profile, ~/.bash_login, ~/.profile을 순서대로 찾아 존재하고 읽을 수 있는 첫 번째 파일부터 명령을 읽고 실행합니다.

.bashrc이러한 파일이 스스로 가져오는 것을 막을 수 있는 방법은 없으므로 내부적으로 확인하는 것이 .bashrc더 안전하고 작업을 단순하게 유지합니다.

관련 정보