Bash在发布后写入后台作业的标准输入

时间:2017-03-16 16:05:22

标签: linux bash gimp

这很天真,但我会试一试 我想用b gimp -i -b - &从bash启动gimp,然后在无限循环中读取dbus信号,并将从这些信号中获得的数据发回到我发布的gimp。 gimp -i -b -启动命令行gimp并等待用户输入,如gnuplot等。但是在命令执行后是否可以从bash访问它的stdin?

理想情况下,我想要这样的工作:

gimp -i -b - &

dbus-monitor --profile "..." --monitor |
while read -r line; do
gimp -b '(mycommand '$line')' &
done

gimp -b '(gimp-quit 0)' &

其中所有gimp cmd &都发送到同一个gimp实例。 如果我可以关闭gimp实例,如果它没有被使用足够长时间并且在需要时再次启动会更好。

没有编写一些守护程序应用程序,是否可以使用bash?

1 个答案:

答案 0 :(得分:4)

简单解决方案

你可以给我们一个简单的管道。将发送脚本部分的命令包装到函数中,并在将其输出汇总到gimp时调用该函数:

#! /bin/bash

sendCommands() {
    dbus-monitor --profile "..." --monitor |
    while read -r line; do
        echo "(mycommand $line)"
    done
    echo "(gimp-quit 0)"
}

sendCommands | gimp -i &

sendCommandsgimp -i将并行运行。每次sendCommands打印一些东西,就会有什么东西落在gimp的标准中 如果这是您的完整脚本,则可以在&之后省略gimp -i

杀死并重新启动Gimp

  

如果我可以关闭gimp实例,如果它的使用时间不够长,并且在需要时再次启动,那会更好。

这比使用timeout命令要复杂得多,因为我们不想在处理某些图像时杀死gimp。我们也不想在消耗事件和发送相应命令之间杀死sendCommands

也许我们可以启动帮助程序来每60秒发送一次dbus事件。让所述事件称为 tick 。刻度线也由sendCommands读取。如果有两个没有命令的刻度线,则应该杀死gimp。

我们使用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