bash를 호출하고 새 셸 내에서 명령을 실행 한 다음 사용자에게 제어권을 다시 제공하는 방법은 무엇입니까?


86

... 그럼, 새로운 bash는 인스턴스를 열고 그 안에 몇 가지 명령을 실행하고 사용자에 대한 제어 다시 제공하기 위해 노력하고이 필수 정말 간단하거나 정말 복잡 하나,하지만 난 그것에 대해 아무것도 찾을 수 없습니다 내부에 그 동일한 인스턴스 .

나는 시도했다 :

$ bash -lic "some_command"

그러나 이것은 some_command새 인스턴스 내에서 실행 된 다음 닫습니다. 나는 그것이 열려 있기를 원합니다.

답변에 영향을 미칠 수있는 한 가지 더 자세한 사항 :이 작업을 수행 할 수 있으면 .bashrc별칭으로 사용 하므로 alias구현에 대한 보너스 포인트 !


별칭에 대한 마지막 부분을 이해하지 못합니다. 별칭은 현재 셸의 컨텍스트에서 실행되므로 해결을 요청하는 문제가 없습니다 (일반적으로 여러 가지 이유로 함수가 별칭보다 낫습니다).
tripleee

2
alias shortcut='bash -lic "some_command"'bashrc 와 같은 것을 넣은 다음 실행 shortcut하고 some_command이미 실행 된 새 셸을 가질 수 있기를 원합니다 .
Félix Saparelli

답변:


65
bash --rcfile <(echo '. ~/.bashrc; some_command')

임시 파일 생성을 제거합니다. 다른 사이트에 대한 질문 :


Windows 10에서이 작업을 시도했습니다 (일괄 "시작"파일 / 스크립트 작성 시도). 결과The system cannot find the file specified.
Doctor Blue

1
@Scott은 단계별로 디버그합니다. 1) cat ~/.bashrc작동합니까? 2) cat <(echo a)작동합니까? 3) bash --rcfile somefile작동합니까?
치로 틸리는郝海东冠状病六四事件法轮功

1
@Scott 우리는 WSL에서이 문제를 만났습니다 (시작 배치 파일에서 bash 시작). 우리의 해결책은 배치가 이해할 수 있도록 일부 문자를 이스케이프하는 것이 었습니다. bash.exe --rcfile ^<^(echo 'source $HOME/.bashrc; ls; pwd'^)Windows 명령 프롬프트에서 실행해야합니다.
user2561747

sudo bash --init-file <(echo "ls; pwd")또는 같은 사용자 전환과 함께 작동하도록하는 방법이 sudo -iu username bash --init-file <(echo "ls; pwd")있습니까?
jeremysprofile


40

이것은 늦은 답변이지만 똑같은 문제가 있었고 Google이 저를이 페이지로 보냈으므로 여기에서 완벽하게 문제를 해결 한 방법이 있습니다.

내가 말할 bash수있는 한, 원래 포스터가하고 싶었던 것을 할 수있는 옵션이 없습니다. 이 -c옵션은 명령이 실행 된 후에 항상 반환됩니다.

깨진 솔루션 : 이것에 대한 가장 간단하고 명백한 시도는 다음과 같습니다.

bash -c 'XXXX ; bash'

이것은 부분적으로 작동합니다 (추가 하위 쉘 레이어가 있음에도 불구하고). 그러나 문제는 하위 셸이 내 보낸 환경 변수를 상속하지만 별칭 및 함수는 상속되지 않는다는 것입니다. 따라서 이것은 어떤 일에는 효과가 있지만 일반적인 해결책은 아닙니다.

더 나은 :이 문제를 해결하는 방법은 동적으로 시작 파일을 만들고이 새로운 초기화 파일로 bash를 호출하여 ~/.bashrc필요한 경우 새 init 파일이 일반 파일을 호출하는지 확인하는 것 입니다.

# Create a temporary file
TMPFILE=$(mktemp)

# Add stuff to the temporary file
echo "source ~/.bashrc" > $TMPFILE
echo "<other commands>" >> $TMPFILE
echo "rm -f $TMPFILE" >> $TMPFILE

# Start the new bash shell 
bash --rcfile $TMPFILE

좋은 점은 임시 초기화 파일이 사용 되 자마자 스스로 삭제되어 올바르게 정리되지 않을 위험이 줄어든다는 것입니다.

참고 : / etc / bashrc가 일반적으로 일반 비 로그인 셸의 일부로 호출되는지 확실하지 않습니다. 그렇다면 / etc / bashrc와 ~/.bashrc.


rm -f $TMPFILE점은한다. 나는 실제로 이것에 대한 사용 사례를 기억하지 못하며 이제는 더 고급 자동화 기술을 사용하지만 이것이 갈 길입니다!
Félix Saparelli 2013 년

8
프로세스 대체가있는 tmp 파일 없음bash --rcfile <(echo ". ~/.bashrc; a=b")
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功 2014

3
임시 파일은 Bash 스크립트가 성공적으로 실행되는 경우에만 정리됩니다. 보다 강력한 솔루션은 trap.
tripleee

5

--rcfileBash에 전달 하여 선택한 파일을 읽도록 할 수 있습니다. 대신이 파일을 읽습니다 .bashrc. (그게 문제라면 ~/.bashrc다른 스크립트에서 출처 를 확인하세요.)

편집 : 따라서 ~/.more.sh다음과 같이 새 셸을 시작하는 기능 은 다음과 같습니다.

more() { bash --rcfile ~/.more.sh ; }

... 그리고 .more.sh쉘이 시작될 때 실행하려는 명령이 있습니다. (별도의 시작 파일을 피하는 것이 우아하다고 생각합니다. 셸이 대화 형이 아니기 때문에 표준 입력을 사용할 수 없지만 임시 위치에있는 here 문서에서 시작 파일을 만든 다음 읽을 수 있습니다.)


3

스크립트를 실행하는 대신 소싱하여 원하는 기능을 얻을 수 있습니다. 예 :

$ cat 스크립트
cmd1
cmd2
$. 스크립트
$이 시점에서 cmd1 및 cmd2가이 쉘 내에서 실행되었습니다.

흠. 작동하지만 모든 것을 포함 할 수있는 방법은 없습니다. alias=''?
Félix Saparelli

1
별칭을 사용하지 마십시오. 대신 함수를 사용하십시오. 다음과 같이 입력 할 수 있습니다. 'foo () {cmd1; cmd2; } '를 시작 스크립트 안에 넣은 다음 foo를 실행하면 현재 셸에서 두 명령이 실행됩니다. 참고 이러한 솔루션 중 어느 것도 당신에게 새로운 쉘을 제공합니다,하지만 당신은 '간부 인 bash는'다음 'foo는'할 수있는
윌리엄 Pursell

1
결코 말하지 마십시오. 별칭은 자신의 자리가
글렌 잭맨

별칭 대신 함수를 사용할 수없는 사용 사례의 예가 있습니까?
William Pursell

3

다음 ~/.bashrc과 같은 섹션에 추가 하십시오.

if [ "$subshell" = 'true' ]
then
    # commands to execute only on a subshell
    date
fi
alias sub='subshell=true bash'

그런 다음 sub.


독창성을위한 포인트. 별칭 자체는 아마도 다음 명령으로 env subshell=true bash누출되지 않으므로 더 좋을 것입니다 . env 사용 vs. export . $subshell
Félix Saparelli 2015 년

당신이 옳습니다. 그러나 나는 그것이 없이도 작동한다는 것을 알았습니다 env. 이 정의되어 있는지 여부를 확인하기 위해 echo $subshell( env | grep subshell당신이 사용하는 대신 ) 사용합니다.
dashohoxha

3

허용되는 답변은 정말 도움이됩니다! 프로세스 대체 (예 :)를 추가하기 위해 <(COMMAND)일부 셸 (예 :)에서 지원되지 않습니다 dash.

제 경우에는 Thunar 파일 관리자에서 사용자 지정 작업 (기본적으로 한 줄 셸 스크립트)을 만들어 셸을 시작하고 선택한 Python 가상 환경을 활성화하려고했습니다. 나의 첫 번째 시도는 :

urxvt -e bash --rcfile <(echo ". $HOME/.bashrc; . %f/bin/activate;")

%fThunar에서 처리하는 가상 환경의 경로는 어디에 있습니까 ? 명령 줄에서 Thunar를 실행하여 오류가 발생했습니다.

/bin/sh: 1: Syntax error: "(" unexpected

그런 다음 내 sh(본질적으로 dash) 프로세스 대체를 지원하지 않는다는 것을 깨달았습니다 .

내 솔루션은 bash추가 수준의 셸을 희생하면서 프로세스 대체를 해석하기 위해 최상위 수준에서 호출하는 것이 었습니다 .

bash -c 'urxvt -e bash --rcfile <(echo "source $HOME/.bashrc; source %f/bin/activate;")'

또는 here-document를 사용하려고했지만 dash성공하지 못했습니다. 다음과 같은 것 :

echo -e " <<EOF\n. $HOME/.bashrc; . %f/bin/activate;\nEOF\n" | xargs -0 urxvt -e bash --rcfile

추신 : 댓글을 게시 할 평판이 충분하지 않습니다. 중재자는 댓글로 이동하거나이 질문에 도움이되지 않는 경우 삭제 해 주시기 바랍니다.


bash를 맨 위에 원하지 않는 경우 (또는없는 경우) 대부분 fifo를 사용하여 프로세스 대체를 직접 구현하는 다양한 문서화 된 방법이 있습니다.
Félix Saparelli

2

daveraja 의 답변에 따라 목적을 해결할 bash 스크립트가 있습니다.

C-shell을 사용 중이고 다음과 같이 C-shell 컨텍스트 / 창을 벗어나지 않고 명령을 실행하려는 경우 상황을 고려하십시오.

실행할 명령어 : * .h, * .c 파일에서만 재귀 적으로 현재 디렉토리의 'Testing'단어를 정확히 검색

grep -nrs --color -w --include="*.{h,c}" Testing ./

해결 방법 1 : C-shell에서 bash로 들어가서 명령을 실행하십시오.

bash
grep -nrs --color -w --include="*.{h,c}" Testing ./
exit

해결 방법 2 : 의도 한 명령을 텍스트 파일에 작성하고 bash를 사용하여 실행합니다.

echo 'grep -nrs --color -w --include="*.{h,c}" Testing ./' > tmp_file.txt
bash tmp_file.txt

해결 방법 3 : bash를 사용하여 같은 줄에서 명령 실행

bash -c 'grep -nrs --color -w --include="*.{h,c}" Testing ./'

해결 방법 4 : sciprt (한 번)를 만들고 이후의 모든 명령에 사용

alias ebash './execute_command_on_bash.sh'
ebash grep -nrs --color -w --include="*.{h,c}" Testing ./

스크립트는 다음과 같습니다.

#!/bin/bash
# =========================================================================
# References:
# https://stackoverflow.com/a/13343457/5409274
# https://stackoverflow.com/a/26733366/5409274
# https://stackoverflow.com/a/2853811/5409274
# https://stackoverflow.com/a/2853811/5409274
# https://www.linuxquestions.org/questions/other-%2Anix-55/how-can-i-run-a-command-on-another-shell-without-changing-the-current-shell-794580/
# https://www.tldp.org/LDP/abs/html/internalvariables.html
# https://stackoverflow.com/a/4277753/5409274
# =========================================================================

# Enable following line to see the script commands
# getting printing along with their execution. This will help for debugging.
#set -o verbose

E_BADARGS=85

if [ ! -n "$1" ]
then
  echo "Usage: `basename $0` grep -nrs --color -w --include=\"*.{h,c}\" Testing ."
  echo "Usage: `basename $0` find . -name \"*.txt\""
  exit $E_BADARGS
fi  

# Create a temporary file
TMPFILE=$(mktemp)

# Add stuff to the temporary file
#echo "echo Hello World...." >> $TMPFILE

#initialize the variable that will contain the whole argument string
argList=""
#iterate on each argument
for arg in "$@"
do
  #if an argument contains a white space, enclose it in double quotes and append to the list
  #otherwise simply append the argument to the list
  if echo $arg | grep -q " "; then
   argList="$argList \"$arg\""
  else
   argList="$argList $arg"
  fi
done

#remove a possible trailing space at the beginning of the list
argList=$(echo $argList | sed 's/^ *//')

# Echoing the command to be executed to tmp file
echo "$argList" >> $TMPFILE

# Note: This should be your last command
# Important last command which deletes the tmp file
last_command="rm -f $TMPFILE"
echo "$last_command" >> $TMPFILE

#echo "---------------------------------------------"
#echo "TMPFILE is $TMPFILE as follows"
#cat $TMPFILE
#echo "---------------------------------------------"

check_for_last_line=$(tail -n 1 $TMPFILE | grep -o "$last_command")
#echo $check_for_last_line

#if tail -n 1 $TMPFILE | grep -o "$last_command"
if [ "$check_for_last_line" == "$last_command" ]
then
  #echo "Okay..."
  bash $TMPFILE
  exit 0
else
  echo "Something is wrong"
  echo "Last command in your tmp file should be removing itself"
  echo "Aborting the process"
  exit 1
fi

2
이것은 완전히 다른 문제에 대한 완전히 다른 대답입니다. (당신이 알아 낸 것은 멋지지만,이 스레드에 속하지 않습니다. 이것이이 사이트에 존재하지 않았다면, 두 번째 문장으로 새로운 질문을 여는 것을 고려하고 나머지는 즉시 스스로 대답하십시오 ... 이것이 처리 방법입니다 ☺) 임시 파일을 전혀 빌드하지 않고 수행하는 방법에 대한 Ciro Santilli의 답변을 참조하십시오.
Félix Saparelli

질문 에 답하려는 시도가 아니기 때문에 응답이 아님 플래그가 지정되었습니다 ( 다른 질문에 답하는 것은 정말 대단한 시도입니다!)
Charles Duffy

0
$ bash --init-file <(echo 'some_command')
$ bash --rcfile <(echo 'some_command')

프로세스 대체를 사용할 수 없거나 사용하지 않으려는 경우 :

$ cat script
some_command
$ bash --init-file script

또 다른 방법:

$ bash -c 'some_command; exec bash'
$ sh -c 'some_command; exec sh'

sh-유일한 방법 ( dash, busybox) :

$ ENV=script sh

좋은 대안이지만 ENV=script, 상위 답변의 노골적인 복사-붙여 넣기와 혼동되지 않도록 상단 섹션 ( 부분 앞 )을 제거하거나 단어를 바꾸면 도움이됩니다.
Félix Saparelli

@ FélixSaparelli 솔직히 말하면 ENV+ sh하나는 다른 답변에 있지만 대부분 텍스트에 묻혀 있거나 불필요한 / 비 필수 코드로 둘러싸여 있습니다. 간단하고 명확한 요약이 모두에게 도움이 될 것이라고 생각합니다.
x-yuri

0

다음은 또 다른 (작동하는) 변형입니다.

그러면 새 그놈 터미널이 열리고 새 터미널에서 bash가 실행됩니다. 사용자의 rc 파일을 먼저 읽은 다음 ls -la대화 형으로 전환하기 전에 새 셸로 실행을 위해 명령 을 보냅니다. 마지막 에코는 실행을 완료하는 데 필요한 새 줄을 추가합니다.

gnome-terminal -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'

나는 또한 더 나은 방향을 위해 색으로 터미널을 장식하는 것이 때때로 유용하다는 것을 알았다.

gnome-terminal --profile green -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'

-1

백그라운드 셸에서 명령 실행

&명령 끝에 추가하십시오 . 예 :

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