명령 실행 후 Bash를 계속 실행하는 방법은 무엇입니까?


29

나는 이런 식으로 뭔가를 실행하고 싶습니다 :

bash -c "some_program with its arguments"

대화식 bash가 some_program종료 후에 계속 실행되도록하십시오 .

나는 seys -c만큼 좋은 방법은 man bash아니라고 확신합니다.

대화식 쉘은 옵션이 아닌 인수와 -c 옵션없이 시작된 쉘입니다.

어떻게해야합니까?

주요 목표는 여기 에 설명되어 있습니다

노트

  • some_program때때로 종료해야합니다
  • 나는 그것을 배경에 넣고 싶지 않다.
  • bash그때 다른 일 을하고 싶어
  • 프로그램을 다시 실행할 수 있기를 원합니다

1
목표가 그렇게 복잡한 경우 여기에서도 설명해야합니다. 그러나 그것은 단지 충고
일뿐입니다

1
나는 가능한 한 짧고 정확하게 설명하려고했습니다. 그러나 나는 대부분의 사람들이 세부 사항에 초점을 맞추지 않고 다른 것을 제안하려고 할 것이라고 기대하지 않았습니다. 명확하게하기 위해 몇 가지 메모를하겠습니다.
pawel7318

다른 질문에서 터미널이 탈출하는 것은 무엇입니까? 설명하는 목표는 가능하지만 I / O 처리가 필요합니다. 일반 서브 쉘은 일반 파일을 통해 터미널 이스케이프 된 I / O를 쉽게 처리하지 못합니다. 당신은 pty.
살펴봐

그건 그렇고, 아래 답변에서 작동하는 유일한 이유는 터미널을 훔치기 때문입니다. 그러나 결국 부모 프로세스가 다시 가져갈 가능성이 있습니다. 그러면 4kb 버퍼를보고 있습니다.
mikeserv

왜 프로그램을 백그라운드에두고 싶지 않습니까? 백그라운드에서 시작하고, 배쉬를하고, 다음과 같이 전경에 놓으십시오.fg
Bernhard

답변:


8
( exec sh -i 3<<SCRIPT 4<&0 <&3                                        
    echo "do this thing"
    echo "do that thing"
  exec  3>&- <&4
  SCRIPT
)

exec $0.또는 스크립트를 사용하여 더 잘 수행 할 수 있습니다. 또는 해당 파일 설명자 중 하나가 현재 사용되지 않는 터미널 장치를 지시하면 도움이 될 것입니다. 다른 프로세스도 해당 터미널을 확인하고 싶습니다.

그건 그렇고, 목표가 스크립트를 실행 한 후에 스크립트 환경을 보존하는 것이 목표라고 가정하면 훨씬 더 나은 서비스를 제공받을 것입니다.

. ./script

쉘의 .dot와는 bash's source하나도과 동일 - 쉘의가 .dot이 거기가 될 것입니다 보장은 결코 비록, POSIX 특별한 쉘 내장으로 지정하고 가까운 당신이 얻을 수있는 보장되기 때문에입니다 ...

위의 내용은 문제가 거의 없지만 예상대로 수행해야합니다. 예를 들어 다음을 수행 할 수 있습니다.

 ( exec sh -i 3<<SCRIPT 4<&0 <&3                                        
    echo "do this thing"
    echo "do that thing"
    $(cat /path/to/script)
    exec  3>&- <&4
    SCRIPT
 )

쉘은 스크립트를 실행하고 대화식 프롬프트로 돌아갑니다- exit스크립트에서 쉘 을 피 하거나 프로세스를 배경으로 하지 않는 한 i / o를/dev/null.

데모:

% printf 'echo "%s"\n' "These lines will print out as echo" \
    "statements run from my interactive shell." \
    "This will occur before I'm given the prompt." >|/tmp/script
% ( exec sh -i 3<<SCRIPT 4<&0 <&3
    echo "do this thing"
    echo "do that thing"
    $(cat /tmp/script)
    exec  3>&- <&4
SCRIPT
)
sh-4.3$ echo "do this thing"
    do this thing
sh-4.3$ echo "do that thing"
    do that thing
sh-4.3$ echo "These lines will print out as echo"
    These lines will print out as echo
sh-4.3$ echo "statements run from my interactive shell."
    statements run from my interactive shell.
sh-4.3$ echo "This will occur before I'm given the prompt."
    This will occur before I'm given the prompt.
sh-4.3$ exec  3>&- <&4
sh-4.3$

많은 JOBS

쉘의 내장 된 작업 관리 옵션에 대해 좀 더 잘 알고 있어야한다고 생각합니다. @Kiwy와 @jillagre는 이미 답변 에서이 부분을 다루었지만 더 자세한 내용을 보증 할 수 있습니다. 그리고 난 이미 내장 한 POSIX 지정 특별 쉘을 언급하지만, 한 set, jobs, fg,bg몇 가지 더, 그리고 또 다른 대답은 보여로 trap하고 kill더 여전히 두 가지이다.

동시에 실행중인 백그라운드 프로세스의 상태에 대한 즉각적인 알림을받지 않은 경우 현재 쉘 옵션이 POSIX 지정 기본값 인으로 설정되어 있기 때문에 대신 -m비동기식으로 가져올 수 있습니다 set -b.

% man set
    b This option shall be supported if the implementation supports the
         User  Portability  Utilities  option. It shall cause the shell to
         notify the user asynchronously of background job completions. The
         following message is written to standard error:
             "[%d]%c %s%s\n", <job-number>, <current>, <status>, <job-name>

         where the fields shall be as follows:

         <current> The  character  '+' identifies the job that would be
                     used as a default for the fg or  bg  utilities;  this
                     job  can  also  be specified using the job_id "%+" or
                     "%%".  The character  '−'  identifies  the  job  that
                     would  become  the default if the current default job
                     were to exit; this job can also  be  specified  using
                     the  job_id  "%−".   For  other jobs, this field is a
                     <space>.  At most one job can be identified with  '+'
                     and  at  most one job can be identified with '−'.  If
                     there is any suspended  job,  then  the  current  job
                     shall  be  a suspended job. If there are at least two
                     suspended jobs, then the previous job also shall be a
   m  This option shall be supported if the implementation supports the
         User Portability Utilities option. All jobs shall be run in their
         own  process groups. Immediately before the shell issues a prompt
         after completion of the background job, a message  reporting  the
         exit  status  of  the background job shall be written to standard
         error. If a foreground job stops, the shell shall write a message
         to  standard  error to that effect, formatted as described by the
         jobs utility. In addition, if a job  changes  status  other  than
         exiting  (for  example,  if  it  stops  for input or output or is
         stopped by a SIGSTOP signal), the shell  shall  write  a  similar
         message immediately prior to writing the next prompt. This option
         is enabled by default for interactive shells.

유닉스 기반 시스템의 가장 기본적인 특징은 프로세스 처리 방법 signals입니다. 나는 이 과정을 더글러스 아담스의 행성에 대한 설명에 비유하는 주제에 관한 깨달은 기사읽었습니다.

"The Hitchhiker 's Guide to the Galaxy에서 Douglas Adams는 우울한 인간 무리와 허벅지에 아주 열심히 물려 인간과 의사 소통을하는 날카로운 이빨을 가진 특정 종류의 동물이 서식하는 매우 둔한 행성에 대해 언급합니다. 커널이 마비 또는 치명적인 신호를 보내서 프로세스와 통신하는 UNIX와 유사하다. 프로세스는 일부 신호를 가로 채서 상황에 적응하려고 시도하지만 대부분은 그렇지 않다. "

이것은을 참조합니다 kill signals.

% kill -l 
> HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS

적어도 위의 인용문은 많은 질문에 대답했습니다. 예를 들어, 나는 항상 그것이 매우 이상하다고 생각했고 전혀 직관적이지 않은 것으로 dd프로세스 를 모니터링하고 싶었다고 생각했다 kill. 그것을 이해 한 후에 말이되었습니다.

나는 대부분의 사람들 정당한 이유 에 적응하려고하지 않는다고 말하고 싶다. 개발자들이 당신에게 중요하다고 생각한 정보로 터미널을 스팸 처리하는 프로세스보다 많은 성가신 것보다 훨씬 더 귀찮을 수있다. .

터미널 구성에 따라 (당신이 확인할 수있는 stty -a) , CTRL+Z를 전달하는 것 세트입니다 SIGTSTP가능성이 셸 현재 전경 프로세스 그룹 리더로, 어느 또한 기본적으로 구성해야 trap하는 신호와 마지막 명령을 일시 중지합니다. @jillagre와 @Kiwy의 답변이 함께 알 수 있듯이 원하는 대로이 기능을 원하는 목적에 맞게 조정하는 것을 막을 수는 없습니다.

SCREEN JOBS

따라서 이러한 기능을 활용하려면 먼저 해당 기능을 이해하고 자신의 요구에 맞게 처리를 사용자 정의해야합니다. 예를 들어, Github 에서 다음에 대한 screen키 바인딩을 포함하는 screenrc를 찾았 습니다 SIGTSTP.

# hitting 'C-z C-z' will run Ctrl+Z (SIGTSTP, suspend as usual)
bind ^Z stuff ^Z

# hitting 'C-z z' will suspend the screen client
bind z suspend

따라서 자식 screen프로세스 또는 screen원하는대로 자식 프로세스 자체로 실행되는 프로세스를 일시 중단하는 것이 간단 합니다.

그리고 바로 다음에 :

% fg  

또는:

% bg

원하는대로 프로세스를 포 그라운드 또는 백그라운드로 설정하십시오. jobs내장 언제든지 당신이 목록을 제공 할 수 있습니다. -l피연산자를 추가하면 pid 세부 사항이 포함됩니다.


매우 흥미로운 것 같습니다. 오늘 나중에이 모든 것을 테스트 할 수 있습니다.
pawel7318

23

다음은 원하는 것을 달성하는 짧은 솔루션이지만 문제를 이해하고 bash가 작동하는 방식을 이해하지 않으면 의미가 없습니다.

bash -i <<< 'some_program with its arguments; exec </dev/tty'

이것은 bash 쉘을 실행 시작 some_program, 이후 some_program종료, 당신은 bash 쉘에 삭제 될 수 있습니다.

기본적으로 우리가하고있는 일은 STDIN에 bash 문자열을 공급하는 것입니다. 그 문자열은 some_program with its arguments; exec </dev/tty입니다. 이것은 bash에게 some_program먼저 시작한 다음 실행 하도록 지시 exec </dev/tty합니다. 따라서 문자열에서 명령을 계속 읽는 대신 bash는에서 읽기 시작 /dev/tty합니다.

이것은 -ibash가 시작될 때 STDIN이 tty인지 확인하고 그렇지 않을 때 확인하기 때문입니다. 그러나 나중에는 대화식 모드로 전환됩니다.


다른 해결책

내가 생각하기에 또 다른 아이디어는 ~/.bashrc파일 의 맨 끝에 다음을 추가하는 것 입니다.

if [[ -n "START_COMMAND" ]]; then
  start_command="$START_COMMAND"
  unset START_COMMAND
  eval "$start_command"
fi

그런 다음 먼저 명령으로 쉘을 시작하려면 다음을 수행하십시오.

START_COMMAND='some_program with its arguments' bash

설명:

이것의 대부분은 명백해야하지만 변수 이름 변경에 대한 공명은 변수를 지역화 할 수 있도록합니다. $START_COMMAND익스포트 된 변수 이므로 쉘의 모든 하위 항목에 의해 상속되며, 다른 bash 쉘이 해당 하위 중 하나 인 경우 명령을 다시 실행합니다. 따라서 값을 내 보내지 않은 새 변수 ( $start_command)에 할당 하고 이전 변수 를 삭제합니다.


둘 이상이 있으면 폭파? 하나의 명령? 아니요, 여전히 작동합니다. 당신은 이식성에 대해 옳습니다. <<<POSIX는 아니지만 두 가지 요소가 있습니다 echo "string here" | bash -i. 그렇다면 /dev/tty리눅스가 있습니다. 그러나 bash를 시작하기 전에 FD를 더핑 한 다음 STDIN을 다시 열 수 있습니다.
Patrick

알았어 알았어 그냥 싸우지 마 나는 POSIX와 이식성에 대해 크게 신경 쓰지 않고 상자와 상자에만 필요합니다. mikeserv의 답변도 확인하지만 지금은 할 수 없습니다.
pawel7318

1
싸우지 않는다 :-). 나는 mikserv의 답변을 존중합니다. 그는 호환성을 위해 간절히 간직했습니다. 둘 다 완전히 유효합니다. 때로는 지나치게 복잡하지 않은 경우 호환성을 위해 갈 것입니다. 이 경우에는 그만한 가치가 없다고 생각했습니다.
Patrick

2
@Patrick /dev/tty은 Linux가 아니라 확실히 POSIX입니다.
jlliagre

2
이봐, whaddayaknow .
패트릭

8

트릭을 수행해야합니다.

bash -c "some_program with its arguments;bash"

편집하다:

다음은 업데이트 후 새로운 시도입니다.

bash -c "
trap 'select wtd in bash restart exit; do [ \$wtd = restart ] && break || \$wtd ; done' 2
while true; do
    some_program with its arguments
done
"
  • 때때로 some_program을 종료해야합니다

를 사용 ControlC하면 다음과 같은 작은 메뉴가 나타납니다.

1) bash
2) restart
3) exit
  • 나는 그것을 배경에 넣고 싶지 않다.

그 경우입니다.

  • 나는 배쉬에 머물고 나서 다른 것을하고 싶다.

"bash"선택을 선택하십시오

  • 프로그램을 다시 실행할 수 있기를 원합니다

"다시 시작"선택을 선택하십시오


나쁘지 않다. .. 그러나 마지막 명령으로 돌아갈 수있을뿐만 아니라 좋을 것이다. 그것에 대한 아이디어가 있습니까? 여기 에 다른 질문이 있는지 확인 하십시오. 그래서 당신은 또 다른 접근법을 제안 할 것입니다
pawel7318

이것은 서브 쉘을 실행합니다. 나는 asker가 스크립트 환경을 보존하려고 노력하고 있다고 생각합니다.
mikeserv

당신에게 jlliagre 감사합니다-좋은 시도하지만별로 유용하지 않습니다. 나는 보통 Ctrl + C를 누르고 그것이 생각하는 것을 할 것으로 기대합니다. 추가 메뉴는 많이 있습니다.
pawel7318

@ pawel7318의 동작은 CTRL+C터미널의 기본 구성이 부작용으로 해석되는 부작용 SIGINT입니다. 에서와 같이 수정할 수 있습니다 stty.
mikeserv

더 명확하게하기 위해 @ pawel7318 SIGINTtrapped위에 있습니다 2.
mikeserv

3

스크립트를 초기화 파일로 전달하면됩니다.

bash --init-file foo.script

또는 명령 행에서 전달할 수 있습니다.

bash --init-file <(echo "ls -al")

--init-file처럼 넓은 초기화 파일 시스템을 읽기 위해 의미되었다 /etc/bash.bashrc당신이 '로 할 수 있습니다 있도록 source스크립트에서 이러한'.


0

나는이 프로그램을 실행 한 후에 이미 쉘로 돌아 가기 때문에 이것을하는 요점을 실제로 보지 못합니다. 그러나 다음과 같이 할 수 있습니다.

bash -c "some_program with its arguments; bash"

프로그램이 실행 된 후 대화식 bash가 시작됩니다.


서브 쉘이 시작됩니다.
mikeserv

0

현재 bash를 열어두기 위해 명령을 백그라운드에 둘 수 있습니다.

some_program with its arguments &

러닝으로 돌아가려면 fg명령 을 사용 ^+z하여 백그라운드에 다시 넣을 수 있습니다.


이번에는 아닙니다. bash 에서이 bash를 실행하고 싶다고 가정합니다.
pawel7318

@ pawel7318 조금 더 설명하면 더 나은 답변을 줄 수 있을까요?
Kiwy

내 다른 질문을 확인 하십시오 .
pawel7318

귀하의 질문이 관련된 경우 @ pawel7318 귀하의 질문에 다른 질문에 대한 링크를 추가하십시오.
Kiwy

1
@ pawel7318 bash여부에 관계없이 프로세스 배경을 처리 할 수 ​​없다면 매우 외계인 셸을 사용하고 있습니다. 그리고 저는 키위에 동의합니다-귀하의 질문에 정보가 있다면 더 나은 정보를 제공 할 것입니다.
mikeserv

0

screen을 사용하여 명령을 실행할 수 있습니다. 그런 다음 명령이 완료된 후 세션에 다시 연결할 수 있습니다.

또는 백그라운드에서 명령을 실행하십시오 some_program with its arguments&. 이렇게하면 명령을 다시 실행하고 명령이 완료되면 명령 상태를 얻을 수 있습니다.


나는 그것을 정확하게 실행하고 screen있지만 백그라운드에 두는 것은 나에게 유용하지 않습니다. 때로는 프로그램을 종료하고 다른 것을 수행하고 다시 실행해야합니다. 그리고 주요 목표는 이것을 빨리하는 것입니다.
pawel7318

@ pawel7318 kill %또는 명령으로 백그라운드 프로그램을 종료 할 수 있습니다 kill %1.
BillThor
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.