简单解决方案
您可以使用简单的管道。总结脚本的命令发送部分为功能和调用功能,而其输出作为管道到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
之后省略&
。
杀死并重启瘸子
甚至会更好,如果,如果它不是用足够长的时间,我可以关闭瘸子实例,并在需要时重新启动。
这比使用timeout
命令稍微复杂一些,因为我们不想在处理某些图像时杀死gimp。我们也不想在消耗事件和发送相应命令之间终止sendCommands
。
也许我们可以启动一个帮助程序来每60秒发送一次dbus事件。让我们说的事件被称为勾号。刻度也由sendCommands
读取。如果两个滴答声之间没有命令,则应该杀死芯片。
我们使用FIFO(也称为命名管道)向gimp发送命令。每当新的gimp进程开始时,我们也会创建一个新的FIFO。这确保针对新gimp进程的命令也被发送到新进程。万一gimp无法在60秒内完成挂起的操作,可能同时有两个gimp进程。
#! /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-monitor ... | while ... done
现在写成while ... done < <(dbus-monitor ...)
。两种版本在循环dbus输出方面都做了同样的事情,但管道|
的版本创建了一个不允许在循环内设置全局变量的子shell。有关更多解释,请参阅SC2031。
谢谢@Socowi,这是一个很好的答案!我只需要添加两个注释:首先,我犯了一个错误,它是一个'gimp -i -b - '不仅仅是'gimp -i',它运行gimp并等待来自stdin的用户输入。其次,你答案的最后部分适用于任何通用应用程序,不仅仅是gimp。但是在gimp的情况下,我们有一个优势 - 我们可以使用'(gimp-message(string-append“处理已完成!))''来打印警告。所以我想我们可以强迫gimp来传达它现在处于空闲模式的事实。 – truf
我想我应该可以运行类似'sendCommands |的东西gimp -i -b - 3>&1 1>&2 2>&3 | processReply&'和grep有关处理结束的消息在'processReply()'中结束。与'gimpIsRunning'之间因此我应该能够得到'gimpIsWorking'全球varaiable与'timeout'办法坚持下去。当然这种方法只能用gimp而不是一般情况。我想知道在这种情况下结果代码是否会更简单? – truf
好点。不幸的是,当扫描gimp的stderr时,事情并没有多少简单。因为我们不知道提前超时(这取决于传入作业从未来)'timeout'是没有用的依然。 'sendCommands | gimp ... | processReply&'也不能使用。我们不能停止并用新的gimp过程替换管道中间的gimp进程。扫描gimp的stderr只有好处:我们可以确保一次只运行一个gimp进程。 – Socowi