두 서버를 시작하는 간단한 bash 스크립트가 있습니다.
#!/bin/bash
(cd ./frontend && gulp serve) & (cd ./backend && gulp serve --verbose)
두 번째 명령이 종료되면 첫 번째 명령이 계속 실행되는 것 같습니다.
명령이 종료되면 다른 명령이 종료되도록 어떻게 변경할 수 있습니까?
백그라운드 프로세스의 오류 수준이 종료되었는지 여부를 확인할 필요는 없습니다.
답변
이렇게하면 두 프로세스가 시작되고 첫 번째 프로세스가 끝날 때까지 기다렸다가 다른 프로세스를 종료합니다.
#!/bin/bash
{ cd ./frontend && gulp serve; } &
{ cd ./backend && gulp serve --verbose; } &
wait -n
pkill -P $$
작동 원리
-
스타트:
{ cd ./frontend && gulp serve; } & { cd ./backend && gulp serve --verbose; } &
위의 두 명령은 백그라운드에서 두 프로세스를 시작합니다.
-
기다림
wait -n
백그라운드 작업이 종료 될 때까지 기다립니다.
-n
옵션으로 인해 bash 4.3 이상이 필요합니다. -
죽임
pkill -P $$
현재 프로세스가 상위 인 작업을 종료합니다. 즉, 여전히 실행중인 백그라운드 프로세스가 종료됩니다.
시스템
pkill
에이 없으면 다음 줄을 바꾸십시오.kill 0
또한 현재 프로세스 그룹을 종료 합니다.
쉽게 테스트 가능한 예
스크립트를 변경하면 gulp
설치 하지 않아도 테스트 할 수 있습니다 .
$ cat script.sh
#!/bin/bash
{ sleep $1; echo one; } &
{ sleep $2; echo two; } &
wait -n
pkill -P $$
echo done
위의 스크립트는 그대로 실행될 수 있으며 bash script.sh 1 3
첫 번째 프로세스가 먼저 종료됩니다. 또는 하나를 실행할 수 있으며 bash script.sh 3 1
두 번째 프로세스가 먼저 종료됩니다. 두 경우 모두 원하는대로 작동 함을 알 수 있습니다.
답변
까다 롭습니다. 여기에 내가 고안 한 것이 있습니다. 그것을 단순화 / 간소화 할 수 있습니다 :
#!/bin/sh
pid1file=$(mktemp)
pid2file=$(mktemp)
stat1file=$(mktemp)
stat2file=$(mktemp)
while true; do sleep 42; done &
main_sleeper=$!
(cd frontend && gulp serve & echo "$!" > "$pid1file";
wait "$!" 2> /dev/null; echo "$?" > "$stat1file"; kill "$main_sleeper" 2> /dev/null) &
(cd backend && gulp serve --verbose & echo "$!" > "$pid2file";
wait "$!" 2> /dev/null; echo "$?" > "$stat2file"; kill "$main_sleeper" 2> /dev/null) &
sleep 1
wait "$main_sleeper" 2> /dev/null
if stat1=$(<"$stat1file") && [ "$stat1" != "" ] && [ "$stat1" != 0 ]
then
echo "First process failed ..."
if pid2=$(<"$pid2file") && [ "$pid2" != "" ]
then
echo "... killing second process."
kill "$pid2" 2> /dev/null
fi
fi
if [ "$stat1" = "" ] && \
stat2=$(<"$stat2file") && [ "$stat2" != "" ] && [ "$stat2" != 0 ]
then
echo "Second process failed ..."
if pid1=$(<"$pid1file") && [ "$pid1" != "" ]
then
echo "... killing first process."
kill "$pid1" 2> /dev/null
fi
fi
wait
if stat1=$(<"$stat1file")
then
echo "Process 1 terminated with status $stat1."
else
echo "Problem getting status of process 1."
fi
if stat2=$(<"$stat2file")
then
echo "Process 2 terminated with status $stat2."
else
echo "Problem getting status of process 2."
fi
- 먼저
while true; do sleep 42; done &
잠자기 / 일시 정지 하는 프로세스 ( )를 시작하십시오 . 두 명령이 특정 시간 (예 : 1 시간) 내에 종료 될 것이라고 확신하는 경우이를 초과하는 단일 절전 모드 (예 :)로 변경할 수 있습니다sleep 3600
. 그런 다음 타임 아웃으로 사용하도록 다음 로직을 변경할 수 있습니다. 즉, 많은 시간이 지난 후에도 프로세스가 계속 실행되면 프로세스를 종료하십시오. (위의 스크립트는 현재 그렇게하지 않습니다.) - 두 개의 비동기 (동시 백그라운드) 프로세스를 시작하십시오.
- 당신은 필요하지 않습니다
./
에 대한cd
. command & echo "$!" > somewhere; wait "$!"
프로세스를 비동기 적으로 시작하고 PID를 캡처 한 다음 대기하는 까다로운 구성입니다. 포 그라운드 (동기식) 프로세스로 만듭니다. 그러나 이것은(…)
전체적으로 백그라운드에 있는 목록 내에서 발생 하므로gulp
프로세스가 비동기 적으로 실행됩니다.gulp
프로세스 중 하나가 종료 된 후 상태를 임시 파일에 기록하고“영구적 휴면”프로세스를 종료하십시오.
- 당신은 필요하지 않습니다
sleep 1
두 번째 프로세스가 PID를 파일에 쓸 기회를 갖기 전에 첫 번째 백그라운드 프로세스가 종료되는 경쟁 조건으로부터 보호합니다.- “영원한 휴면”프로세스가 종료 될 때까지 기다리십시오. 위에서 설명한대로 프로세스 중 하나 가
gulp
종료 된 후에 발생합니다 . - 어떤 백그라운드 프로세스가 종료되었는지 확인하십시오. 실패하면 다른 사람을 죽이십시오.
- 한 프로세스가 실패하고 다른 프로세스를 종료 한 경우 두 번째 프로세스가 완료되어 상태를 파일에 저장하기를 기다립니다. 첫 번째 프로세스가 성공적으로 완료되면 두 번째 프로세스가 완료 될 때까지 기다리십시오.
- 두 프로세스의 상태를 확인하십시오.
답변
완전성을 위해 여기에 내가 사용한 것이 있습니다 :
#!/bin/bash
(cd frontend && gulp serve) &
(cd backend && gulp serve --verbose) &
wait -n
kill 0
이것은 Git for Windows 2.5.3 64 비트에서 작동합니다. 이전 버전에서는 -n
옵션을 허용하지 않을 수 있습니다 wait
.
답변
내 시스템 (Centos)에서는 그렇게 wait
하지 않았습니다 -n
.
{ sleep 3; echo one; } &
FOO=$!
{ sleep 6; echo two; } &
wait $FOO
pkill -P $$
이것은 “둘 중 하나”를 기다리지 않고 첫 번째를 기다립니다. 그러나 어떤 서버가 먼저 중지되는지 알면 여전히 도움이 될 수 있습니다.