シンプルなソリューション
私たちは簡単なパイプを使用できます。関数にスクリプトの一部を送信するコマンドをラップしてGIMPにその出力をパイプしながら、その関数を呼び出します。
#! /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のstdinに上陸します。
完全なスクリプトの場合はgimp -i
の後に&
を省略することができます。私はそれが十分な長さのために使用されていない場合はGIMPのインスタンスを閉じて、それが必要なとき、再び起動することができれば
殺害し、再起動のGimp
はさらに良いでしょう。
timeout
コマンドを使用するよりも少し複雑になります.Gimpがまだ画像を処理している間にkillしたくないからです。また、イベントの消費と対応するコマンドの送信の間にsendCommands
を殺すことは望ましくありません。
おそらく60秒ごとにdbusイベントを送信するヘルパープロセスを開始することができます。そのイベントをと呼び、としましょう。ダニはsendCommands
によっても読み取られます。間にコマンドがない2つのティックがある場合、gimpを殺す必要があります。
私たちは、FIFO(名前付きパイプとも呼ばれます)を使用して、gimpにコマンドを送信します。新しいgimpプロセスが始まるたびに、新しいFIFOも作成されます。これにより、新しいgimpプロセスを対象とするコマンドも新しいプロセスに送信されます。 gimpが保留中の操作を60秒以内に完了できない場合、同時に2つのgimpプロセスが存在する可能性があります。 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を参照してください。
ありがとうございます@ソコウイ、それは素晴らしい答えです!私はちょうど間違いを犯しました。まず、gimpを実行し、stdinからのユーザ入力を待つのは 'gimp -i'だけではなく、' gimp -i -b --'です。第二に、答えの最後の部分は、gimpだけでなく、一般的なアプリにも適しています。しかし、gimpの場合には利点があります。 '(gimp-message(string-append"処理が完了しました!)) 'でstderrに警告を表示させることができます。だから私は今、アイドルモードに入っているという事実をgimpに伝えるように強制することができます。 – truf
私はsendCommandsのようなものを実行できるはずです。 gimp -i -b-3>&gt;&2&gt;&3 | processReply& 'とprocessreeply()'の処理に関するgrepメッセージが表示されます。したがって、 'gimpIsRunning'の中で、私は' gimpIsWorking'をグローバルに可変にでき、 'timeout'アプローチに固執する必要があります。もちろん、このようなアプローチはgimpのみで可能であり、一般的ではありません。この場合、結果コードが簡単になるのだろうか? – truf
良い点。残念ながら、gimpのstderrをスキャンするときには、それほど単純ではありません。私たちは事前にタイムアウトを知っていないので(これは将来の着信ジョブに依存します)、 'timeout'はまだ役に立たないです。 'sendCommands | gimp ... | processReply& 'も使用できません。パイプラインの途中にあるgimpプロセスを停止し、新しいgimpプロセスに置き換えることはできません。 gimpの標準エラーをスキャンするだけの利点:一度に1つのgimpプロセスしか実行しないようにすることができます。 – Socowi