예를 들어 간단한 Node.js 서버가 있다고 가정해 보겠습니다.
const http = require('http');
const server = http.createServer((req,res) => res.end('foobar'))
server.listen(3000, () => {
console.log(JSON.stringify({"listening": 3000}));
});
그런 다음 bash를 사용하십시오.
#!/usr/bin/env bash
node server.js | while read line; do
if [[ "$line" == '{"listening":3000}' ]]; then
:
fi
done
# here I want to process more crap
내 목표는 서버가 실제로 요청 수신을 시작한 후에만 스크립트를 계속 실행하는 것입니다. 내가 생각할 수 있는 가장 좋은 점은 다음과 같습니다.
#!/usr/bin/env bash
mkfifo foo
mkfifo bar
(node server.js &> foo) &
(
while true; do
cat foo | while read line; do
if [[ "$line" != '{"listening":3000}' ]]; then
echo "$line"
continue;
fi
echo "ready" > bar
done
done
) &
cat bar && {
# do my thing here?
}
이 작업을 수행하는 더 깨끗하고 쉬운 방법이 있습니까? 서버가 준비되면 계속하고 싶습니다. 제가 아는 유일한 좋은 방법은 stdout을 사용하여 메시지를 인쇄하고 해당 메시지를 수신하는 것입니다.
답변1
헤비급 접근 방식은 다음을 사용하는 것입니다.예상되는
#!/usr/bin/env expect
spawn node server.js
set timeout -1
expect {{"listening":3000}}
# now you can process all the crap, but in Expect
interact
Bash를 사용하면 Bash에서 foo 파일을 처리할 필요가 없습니다. 어때요?
#!/usr/bin/env bash
node server.js &> server.out &
# busy wait
while true; do
grep -q '{"listening":3000}' server.out && break
sleep 1
done
# continue crap processing
서버를 사용하는 동안 서버를 데몬화할 수 있습니다.
node server.js </dev/null &> server.out &
disown $!
답변2
expect
Glenn의 대답은 좋은 일반적인 해결책인 것 같습니다.
더 쉬운 방법을 원하거나 기대치를 원하지 않거나 설치할 수 없는 경우 bash의 더 작은 버전이 있습니다.
#!/usr/bin/env bash
process() {
# do your stuff
echo ok
}
node server.js | ( grep -L '{"listening":3000}' ; process ) &
나는 grep의 -L 옵션(-l도 잘 작동하지만 출력을 생성함)을 활용하여 일치 항목을 찾는 즉시 반환합니다. 그런 다음 제어는 처리 기능으로 전달되며 원하는 경우 출력을 계속 읽을 수도 있습니다.
wait
서버가 종료되기 전에 스크립트가 반환되지 않도록 하려면 끝에 이를 추가하세요.