(“super”) 쉘로 즉시 돌아 가지 않고 초기 명령으로 대화식 bash 서브 쉘을 실행하십시오.


86

bash 서브 쉘을 실행하고 싶고 (1) 몇 가지 명령을 실행 한 다음 (2) 원하는대로 서브 쉘에 남아 있습니다. 나는 이들 각각을 개별적으로 할 수 있습니다.

  1. -c플래그를 사용하여 명령을 실행하십시오 .

    $> bash -c "ls; pwd; <other commands...>"

    그러나 명령이 실행 된 후 즉시 "super"쉘로 돌아갑니다. 대화 형 서브 쉘을 실행할 수도 있습니다.

  2. bash프로세스를 시작하십시오 .

    $> bash

    명시 적으로 말할 때까지 서브 쉘을 종료하지 않지만 초기 명령을 실행할 수는 없습니다. 내가 찾은 가장 가까운 솔루션은 다음과 같습니다.

    $> bash -c "ls; pwd; <other commands>; exec bash"

    하나의 서브 쉘에서 주어진 명령을 실행 한 다음 상호 작용을 위해 별도의 명령을 열어서 작동하지만 원하는 방식은 아닙니다.

한 줄로하고 싶습니다. 일단 서브 쉘을 빠져 나가면 사고없이 일반 "슈퍼"쉘로 되돌아 가야합니다. 방법이 있어야합니다 ~~

NB : 내가 묻지 않은 것은 ...

  1. bash 맨 페이지를 어디서 얻을 수 있는지 묻지 않습니다.
  2. 파일에서 초기화 명령을 읽는 방법을 묻지 않습니다 ...이 작업을 수행하는 방법을 알고 있습니다. 원하는 솔루션이 아닙니다.
  3. tmux 또는 gnu 화면 사용에 관심이 없음
  4. 이에 대한 맥락에 관심이 없습니다. 즉, 질문은 일반적인 것으로 의도되며 특정 목적을위한 것이 아닙니다.
  5. 가능한 경우 원하는 것을 달성하지만 "더러운"방식으로 해결 방법을 사용하고 싶지 않습니다. 그냥 한 줄로하고 싶습니다. 특히 저는 다음과 같은 일을하고 싶지 않습니다xterm -e 'ls'

Expect 솔루션을 상상할 수는 있지만 원하는 단일 라이너는 아닙니다. 어떤 방법으로 exec bash솔루션이 적합하지 않습니까?
glenn jackman

@glennjackman 죄송합니다. 전문 용어에 익숙하지 않습니다. "예상 솔루션"이란 무엇입니까? 또한 exec bash솔루션에는 두 개의 개별 서브 쉘이 포함됩니다. 하나의 연속 서브 쉘을 원합니다.
SABBATINI Luca

3
이것의 exec장점 첫 번째 서브 쉘을 두 번째 서브 쉘로 대체 하므로 부모 아래에 1 개의 쉘만 남게 된다는 것 입니다. 초기화 명령이 환경 변수를 설정하면 실행 된 쉘에 존재합니다.
glenn jackman


2
그리고의 문제는 exec당신이 그런 비 수출 변수, 함수, 별칭, ...로, 환경을 통해 서브 쉘로 아래로 통과 아니에요 아무것도 잃을 것입니다
커트 J. 샘슨

답변:


77

임시 명명 된 파이프를 사용 하여 쉽게 수행 할 수 있습니다 .

bash --init-file <(echo "ls; pwd")

이 답변에 대한 크레딧은 Lie Ryan 의 의견입니다 . 나는 이것이 실제로 유용하다는 것을 알았고 주석에서 눈에 띄지 않기 때문에 그것이 자신의 대답이어야한다고 생각했습니다.


9
이것은 아마도 $HOME/.bashrc실행되지 않음을 의미합니다 . 임시 명명 된 파이프에서 포함되어야합니다.
Hubro

9
명확히하기 위해 다음과 같이 :bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
Hubro

5
이것은 너무 거칠지 만 작동합니다. 나는 bash가 이것을 직접 지원하지 않는다고 믿을 수 없다.
Pat Niemeyer

2
@Gus .ss64.com/bash/source.htmlsource 명령 의 동의어입니다 .
조나단 포터

1
sudo bash --init-file <(echo "ls; pwd")또는 과 같은 사용자 전환 작업을 수행하는 방법이 sudo -iu username bash --init-file <(echo "ls; pwd")있습니까?
jeremysprofile

10

임시 파일을 사용하여 로터리 방식 으로이 작업을 수행 할 수 있지만 두 줄이 필요합니다.

echo "ls; pwd" > initfile
bash --init-file initfile

좋은 효과를 얻으려면 임시 파일을 포함 시켜서 임시 파일을 제거 할 수 있습니다 rm $BASH_SOURCE.
Eduardo Ivanec

에두아르도, 고마워 좋은 해결책이지만 ... 파일 I / O를 사용 하지 않고서 는 이 작업을 수행 할 수 없습니다 . 파일이 혼합되어 들어간 순간 임의의 임시 파일을 만드는 방법에 대해 걱정하고 나서 언급했듯이 삭제하는 이유 때문에이를 자체 포함 명령으로 유지하는 것이 확실한 이유가 있습니다. 내가 엄격하고 싶다면이 방법으로 훨씬 더 많은 노력이 필요합니다. 따라서보다 최소한의 우아한 솔루션에 대한 요구가 있습니다.
SABBATINI 루카

1
@ SABBATINILuca : 나는 그런 말을하지 않습니다. 이것은 단지 방법이며 mktemp@cjc가 지적한 임시 파일 문제를 해결합니다. Bash stdin에서 init 명령을 읽는 것을 지원할 있지만 내가 알 수있는 한은 아닙니다. Specyfing -(는 파이프 라인을 감지 아마 때문에) 초기화 파일로 그들에게 절반 작품 배관,하지만 배쉬는 종료합니다. 우아한 솔루션 IMHO는 exec를 사용하는 것입니다.
Eduardo Ivanec

1
이것도 일반 bash 초기화를 무시하지 않습니까? @SABBATINILuca 이것으로 무엇을 달성하려고합니까? 왜 쉘을 자동 실행하여 일부 명령을 실행 한 다음 해당 쉘을 열어 두어야합니까?
user9517

11
이것은 오래된 질문이지만 Bash는 다음 구문을 사용하여 임시 명명 된 파이프를 만들 수 있습니다. bash --init-file <(echo "ls; pwd").
Lie Ryan

5

대신 이것을 시도하십시오 :

$> bash -c "ls;pwd;other commands;$SHELL"

$SHELL 대화식 모드에서 셸을 열고로 닫기를 기다 exit립니다.


9
참고로, 나중에 새 셸이 열리므로 명령 중 하나라도 현재 셸 상태에 영향을주는 경우 (예 : 파일 소싱) 예상대로 작동하지 않을 수 있습니다.
ThiefMaster

3

내가 언급 한 "예상 솔루션"은 Expect 프로그래밍 언어로 bash 쉘을 프로그래밍하는 것입니다 .

#!/usr/bin/env expect
set init_commands [lindex $argv 0]
set bash_prompt {\$ $}              ;# adjust to suit your own prompt
spawn bash
expect -re $bash_prompt {send -- "$init_commands\r"}
interact
puts "exiting subshell"

다음과 같이 실행하십시오. ./subshell.exp "ls; pwd"


나는 이것이 역사에 명령을 등록하는 이점을 가질 것이라고 생각한다. 또한이 경우 bashrc / profile이 실행되는지 궁금합니다.
muhuk

이것은 당신이 다른 솔루션으로는 할 수없는 명령을 기록에 넣을 수 있음을 확인했습니다. .screenrc 파일에서 프로세스를 시작하는 데 좋습니다. 시작된 프로세스를 종료하면 화면 창이 닫히지 않습니다.
Dan Sandberg

1

네이티브 서브 쉘을 사용하지 않는 이유는 무엇입니까?

$ ( ls; pwd; exec $BASH; )
bar     foo     howdy
/tmp/hello/
bash-4.4$ 
bash-4.4$ exit
$

명령을 괄호로 묶으면 bash가 하위 프로세스를 생성하여 이러한 명령을 실행할 수 있으므로, 예를 들어 부모 셸에 영향을주지 않고 환경을 변경할 수 있습니다. 이것은 기본적으로보다 읽기 쉽다 bash -c "ls; pwd; exec $BASH".

그래도 장황하게 보이면 두 가지 옵션이 있습니다. 하나는이 스 니펫을 함수로 사용하는 것입니다.

$ run() { ( eval "$@"; exec $BASH; ) }
$ run 'ls; pwd;'
bar     foo     howdy
/tmp/hello/
bash-4.4$ exit
$ run 'ls;' 'pwd;'
bar     foo     howdy
/tmp/hello/
bash-4.4$ exit
$

다른 하나는 exec $BASH더 짧게 만드는 것입니다 .

$ R() { exec $BASH; }
$ ( ls; pwd; R )
bar     foo     howdy
/tmp/hello/
bash-4.4$ exit
$

R탈출 문자열로 연주 할 필요가 없으므로 개인적으로 접근 방식이 더 좋습니다.


1
OP가 염두에 둔 시나리오에 exec를 사용하는주의 사항이 있는지 확실하지 않지만 문자열 탈출 문제없이 일반 bash 명령을 사용하기 때문에 이것이 가장 좋은 해결책입니다.
피터

1

경우 sudo -E bash작동하지 않습니다, 나는 지금까지 내 기대를 충족 다음을 사용 :

sudo HOME=$HOME bash --rcfile $HOME/.bashrc

새 세션에 일부 시스템에서 기본적으로 발생하는 루트 HOME이 아닌 HOME을 사용자의 HOME으로 설정하기 때문에 HOME = $ HOME을 설정했습니다.


0

보다 우아 --init-file하지만 아마도 더 유용합니다.

fn(){
    echo 'hello from exported function'
}

while read -a commands
do
    eval ${commands[@]}
done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.