이 질문이 이전에 제기되고 답변된 것으로 의심되지만 검색이 올바른지 확실하지 않습니다.
시작할 때 URL과 포트가 포함된 줄을 출력하는 종료되지 않는 프로세스(서버)가 있습니다. 해당 줄을 변수로 캡처하여 다른 프로그램에 전달할 수 있도록 하고 싶습니다.
그래서 나는 다음과 같이하려고합니다 :
% export URL=`server start` &
URL
그러나 (제 생각에는 :-)) server
종료되지 않고 계속 실행되기 때문에 설정되지 않습니다 .
server
다른 곳에서 사용할 수 있도록 인쇄된 URL을 변수로 캡처하려면 어떻게 해야 합니까 ?
답변1
다음을 시도해 볼 수 있습니다.
server start &
cat /proc/${!}/fd/1
그러면 서버가 시작되고 $!해당 ID가 반환됩니다. fd/1은 /proc를 통해 사용할 수 있는 프로세스의 표준 출력입니다.
참고: 다른 프로세스 ID를 반환할 수 있으므로 start와 $! 사이에 다른 코드 줄이 있어서는 안 됩니다.
답변2
해결책
FIFO(명명된 파이프)를 생성합니다. 다른 사용자로부터 숨겨야 하는 경우
mktemp -d
사전에 임시 디렉터리를 만들고 그 안에 FIFO를 만듭니다(이 답변에서는 간결성을 위해 이 작업을 수행하지 않습니다).mkfifo myfifo
서버 프로세스가 FIFO에 쓰도록 하고, FIFO에서 스크립트를 읽도록 합니다. 서버를 시작한 후 읽기 위해 FIFO를 열었다가 닫으면(리더가 없도록) SIGPIPE가 서버 프로세스로 전송되므로 미리 읽기용으로 FIFO를 열고 열어 두는 것이 좋습니다. 반면에 FIFO를 미리 여는 것은홀로블록을 읽고 일부 프로세스가 쓰기를 위해 FIFO를 열 때까지 기다립니다. 이 문제를 해결하려면 읽기 및 쓰기를 위해 FIFO를 열고 나중에 설명자를 닫습니다.
exec 3<>myfifo
백그라운드에서 서버를 시작하고 FIFO에 쓰도록 합니다.
server start >&3 &
(
>&3
그리고>myfifo
기술적으로 다릅니다. 우리에게는 두 가지 형식 모두 여기에서 작동합니다).FIFO에서 정확히 한 행을 읽습니다.
<&3 IFS= read -r URL
(
<&3
그리고<myfifo
기술적으로 다릅니다. 우리에게는 두 가지 형식 모두 여기에서 작동합니다).cat
백그라운드에서 시작하고 프로세스가 스크립트의 표준 출력으로 인쇄되도록 합니다(또는 출력을 다른cat
것으로 리디렉션하거나/dev/null
필요에 따라 조정).server
이 단계를 생략하면 FIFO에 너무 많은 양이 인쇄되는 경우 차단이 발생합니다.cat
이 작업은 수행한 작업 이후 프로세스가 아무 것도 인쇄하지 않을 것이라는 확신이 있는 경우에만 필요합니다.read
그런 경우에도cat
아무런 해를 끼치지 않습니다.일반적으로 또 다른 문제가 있습니다.
server
읽기 위해 열려 있는 모든 설명자를 닫은 후 SIGPIPE를 사용하여 종료할 수 있습니다. 우리는server
글쓰기에 대한 설명자를 스스로 보유합니다.그리고읽어 SIGPIPE가 발생하지 않습니다. 이런 일이 발생하면cat
FIFO에서 읽기를 시작하면 문제가 해결됩니다.그런 다음 시작하십시오
cat
.<myfifo cat 3>&- &
myfifo
여기서는 읽기만 활성화 하고cat
쓰기를 허용하는 설명자를 상속하는 것은 허용되지 않습니다. 중요한 점은cat
쓰기를 위해 FIFO를 열어두어서는 안 된다는 것입니다. 이것은 나중에 중요할 것입니다.설명자를 닫아 FIFO만 열어
cat
둡니다 .server
FIFO 연결을 해제할 수도 있습니다(이렇게 해도 FIFO를 사용하는 프로세스가 중단되지는 않습니다).exec 3>&- rm myfifo
이렇게 하면 스크립트의 향후 자손이 해당 설명자를 상속하지 않습니다.
작업
$URL
.종료 시
server
다른 프로세스는 쓰기 위해 FIFO를 열지 않으며cat
EOF 조건을 만나 종료됩니다. 이때 우리가 시작하는 방법이cat
중요합니다. 상속된 파일 설명자가 보유 되면cat
공식적으로 FIFO의 작성자가 되므로 자동으로 종료될 수 없습니다. 로그아웃cat
후에는 자동으로 로그아웃 되도록 보장합니다server
.스크립트가 끝나면 아마도
wait
다음과 같은 일이 일어나기를 원할 것입니다.wait
(이는 다른 백그라운드 작업이 없다고 가정합니다.) 이것이 없으면
wait
스크립트가 이전에 종료되어server
백그라운드 에server
남아 있을 수 있습니다.cat
스크립트가 필요한지 여부를 결정합니다wait
.
개념의 증거
#!/bin/sh
# fake server
server() {
echo 'example.com'
for i in 1 2 3 4 5 6 7; do echo 'server running'; sleep 1; done
}
mkfifo myfifo
exec 3<>myfifo
server start >&3 &
<&3 IFS= read -r URL
<myfifo cat 3>&- &
exec 3>&-
rm myfifo
echo "The URL is $URL"
sleep 2
echo "Still working with $URL"
sleep 2
echo "Done. Waiting for the server to close."
wait