나는 다음과 같은 것을 실행하고 싶습니다 :
bash -c "some_program with its arguments"
그러나 대화형 bash가 some_program
종료된 후에도 계속 실행되도록 하십시오.
-c
나는 이것이 좋은 접근 방식이 아니라고 확신합니다 man bash
.
대화형 쉘은 옵션이 아닌 인수와 -c 옵션 없이 시작됩니다.
그럼 어떻게 해야 할까요?
설명된 주요 목표여기
노트
some_program
수시로 종료 해야 해요- 배경에 넣고 싶지 않아요
bash
난 남아서 다른 일을 하고 싶어- 프로그램을 다시 실행하고 싶습니다.
답변1
다음은 원하는 작업을 수행하는 더 짧은 솔루션이지만 문제와 bash 작동 방식을 이해하지 않으면 의미가 없을 수 있습니다.
bash -i <<< 'some_program with its arguments; exec </dev/tty'
그러면 bash 쉘이 시작 some_program
되고 종료 시 some_program
대화형 쉘이 시작됩니다.
기본적으로 우리가 하는 일은 bash의 STDIN에 문자열을 입력하는 것입니다. 이 문자열은 bash에게 시작 some_program
하고 실행하라고 지시합니다 exec </dev/tty
. exec </dev/tty
Bash에게 우리가 제공한 문자열에서 STDIN을 전환하도록 지시하여 /dev/tty
대화형으로 만듭니다.
이는 -i
bash가 시작될 때 STDIN이 tty인지 확인하지만 bash가 시작될 때는 그렇지 않기 때문입니다. 하지만 앞으로는 그렇게 할 것이므로 bash를 대화형 모드로 강제 전환합니다.
또 다른 솔루션
제가 생각하기에 이식성이 매우 좋은 또 다른 아이디어는 파일 끝에 다음을 추가하는 것입니다 ~/.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
)에 값을 할당하고 이전 변수를 삭제합니다.
답변2
( 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.
Unix 기반 시스템의 매우 기본적인 특징은 프로세스를 처리하는 방식입니다 signals
. 언젠가 기사를 읽었는데영감을 주는 기사피험자는 그 과정을 Douglas Adams의 지구 설명에 비유했습니다.무엇을 해야할지:
“은하수를 여행하는 히치하이커를 위한 안내서에서 Douglas Adams는 우울한 인간 집단과 인간의 허벅지를 깨물어 통신하는 날카로운 이빨을 가진 동물이 살고 있는 극도로 황량한 행성에 대해 설명합니다. 커널은 프로세스와 통신합니다. 마비 또는 치명적인 신호가 발생하면 프로세스는 일부 신호를 가로채서 상황에 적응하려고 시도할 수 있지만 대부분의 프로세스는 그렇지 않습니다."
이는 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
전달하도록 설정되어 있을 것이며 , 기본적으로 이를 알리고 마지막 명령을 일시 중단하도록 구성해야 합니다. 다시 말하지만, @jillagre와 @Kiwy의 답변에서 알 수 있듯이 이 기능을 목적에 맞게 원하는 대로 조정할 수 있습니다.SIGTSTP
trap
SCREEN JOBS
따라서 이러한 기능을 활용하려면 먼저 해당 기능을 이해하고 필요에 따라 처리 방법을 사용자 정의해야 합니다. 예를 들어, 방금 발견했습니다.Github의 이 screenrc여기에는 screen
다음 키 바인딩이 포함됩니다 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
언제든지 이러한 목록을 제공할 수 있습니다. add -l
피연산자에는 pid 세부정보가 포함됩니다.
답변3
이렇게 하면 트릭을 수행할 수 있습니다.
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" 옵션을 선택하세요
- 프로그램을 다시 실행하고 싶습니다.
"다시 시작" 옵션을 선택하세요
답변4
$ bash --init-file <(echo 'some_program with its arguments')
$ bash --rcfile <(echo 'some_program with its arguments')
프로세스 대체를 사용할 수 없는 경우:
$ cat script
some_program with its arguments
$ bash --init-file script
그리고 sh
( dash
, busybox
):
$ ENV=script sh
또는:
$ bash -c 'some_program with its arguments; exec bash'
$ sh -c 'some_program with its arguments; exec sh'