간단한 해결책
간단한 파이프로 만들 수 있습니다. 김프로 출력을 파이프하면서 그 기능을 함수로 스크립트의 명령 전송 부분을 감싸고 전화 :
#! /bin/bash
sendCommands() {
dbus-monitor --profile "..." --monitor |
while read -r line; do
echo "(mycommand $line)"
done
echo "(gimp-quit 0)"
}
sendCommands | gimp -i &
sendCommands
및 gimp -i
가 병렬로 실행됩니다. sendCommands
이 무언가를 프린트 할 때마다, 그 무언가는 김프의 표준 입력에 도착할 것입니다.
전체 스크립트 인 경우 gimp -i
뒤에 &
을 생략 할 수 있습니다. 나는 그것을 충분히 오랫동안 사용되어 있지 않은 경우 김프 인스턴스를 닫고 필요할 때 다시 시작할 수 있다면
죽이고 다시 시작 김프
더 나은 것입니다.
이것은 일부 이미지를 처리하는 동안 김프를 죽이지 않으므로 timeout
명령을 사용하는 것보다 약간 복잡합니다. 또한 이벤트 소비와 해당 명령 전송 사이에 sendCommands
을 삭제하지 않으려합니다.
아마도 60 초마다 dbus 이벤트를 보내도록 도우미 프로세스를 시작할 수 있습니다. 이 이벤트를 tick이라고합시다. 진드기도 sendCommands
에 의해 읽혀집니다. 그 사이에 명령이없는 두 개의 틱이 있으면 김프를 죽여야합니다.
김프에 명령을 보내기 위해 FIFO (named pipes)를 사용합니다. 새로운 김프 프로세스가 시작될 때마다 새로운 FIFO도 생성됩니다. 이렇게하면 새로운 김프 프로세스를 목표로하는 명령도 새 프로세스로 전송됩니다. 김프가 60 초 이내에 대기중인 작업을 완료 할 수없는 경우 동시에 두 번의 김프 프로세스가있을 수 있습니다. dbus-monitor ... | while ... done
지금 while ... done < <(dbus-monitor ...)
로 작성되어
는
#! /bin/bash
generateTicks() {
while true; do
# send tick over dbus
sleep 60
done
}
generateTicks &
gimpIsRunning=false
wasActive=false
sleepPID=
fifo=
while read -r line; do
if eventIsTick; then # TODO replace "eventsIsTick" with actual code
if [[ "$wasActive" = false ]]; then
echo '(gimp-quit 0)' > "$fifo" # gracefully quit gimp
gimpIsRunning=false
[[ "$sleepPID" ]] && kill "$sleepPID" # close the FIFO
rm -f "$fifo"
fi
wasActive=false
else
if [[ "$gimpIsRunning" = false ]]; then
fifo="$(mktemp -u)"
mkfifo "$fifo"
sleep infinity > "$fifo" & # keep the FIFO open
sleepPID="$!"
gimp -i < "$fifo" &
gimpIsRunning=true
fi
echo "(mycommand $line)" > "$fifo"
wasActive=true
fi
done < <(dbus-monitor --profile "..." --monitor)
echo '(gimp-quit 0)' > "$fifo" # gracefully quit gimp
[[ "$sleepPID" ]] && kill "$sleepPID" # close the FIFO
rm -f "$fifo"
참고. 두 버전 모두 dbus의 출력에 대해 루핑한다는 측면에서 동일한 작업을 수행하지만 파이프가있는 버전 |
은 루프 내부에 전역 변수를 설정할 수없는 서브 쉘을 만듭니다. 자세한 설명은 SC2031을 참조하십시오.
감사합니다. @Socowi, 훌륭한 답변입니다.난 그냥 2 노트를 추가 할 수 있습니다 : 첫째로 나는 실수를했습니다. 그것은 김프를 실행하고 표준 입력으로부터 사용자 입력을 기다리고있는'gimp -i'뿐만 아니라'gimp -i -b -'입니다. 둘째, 대답의 마지막 부분은 김프뿐만 아니라 일반 앱에도 적합합니다. 그러나 김프의 경우 우리는 하나의 장점을 가지고 있습니다.'(gimp-message (문자열 추가) "처리가 완료되었습니다!))'로 stderr에 경고를 인쇄 할 수 있습니다. 그래서 우리는 김프가 유휴 모드에 있다는 사실을 알려주도록 강제 할 수 있습니다. – truf
나는 sendCommands와 같은 것을 실행할 수 있어야한다고 생각한다. gimp -i -b-3> & 1 1> & 2 2> & 3 | processReply &'와 process에 대한 grep 메시지는'processReply()'에서 끝납니다. 따라서'gimpIsRunning'을 통해'gimpIsWorking' 글로벌 변수를 가변적으로 사용할 수 있어야하고'timeout' 접근법을 고수 할 수 있어야합니다. 물론 그러한 접근은 김프만으로 가능하고 일반적인 경우는 아닙니다. 결과 코드가이 경우 더 간단 해지는지 궁금합니다. – truf
좋은 지적. 불행히도 gimp의 stderr를 검사 할 때 상황이 훨씬 단순하지 않습니다. 우리는 미리 타임 아웃을 알지 못하기 때문에 (그것은 미래의 들어오는 작업에 달려있다.)'timeout'은 여전히 유용하지 않다. 'sendCommands | 김프 ... | processReply &'도 사용할 수 없습니다. 우리는 파이프 라인의 중간에있는 김프 프로세스를 중지하고 새로운 김프 프로세스로 대체 할 수 없습니다. 김프의 표준 오류를 검사 할 때만 얻을 수있는 이점 : 우리는 한 번에 한 번의 김프 프로세스 만 실행할 수 있습니다. – Socowi