Bash 在启动后写入后台作业的标准输入
Bash write to background job's stdin after its launch
这很天真,但我会试一试。
我想从 bash 和 gimp -i -b - &
启动 gimp,然后在无限循环中读取 dbus 信号,然后从这些信号获得的 post 数据返回到我启动的 gimp。 gimp -i -b -
启动命令行 gimp 并等待用户输入,如 gnuplot 等。但是在命令执行后是否可以从 bash 访问其标准输入?
理想情况下,我想要这样的东西工作:
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 而无需编写一些守护程序应用程序?
简单的解决方案
你可以给我们一个简单的管道。将发送部分脚本的命令包装到一个函数中,并在将其输出通过管道传输到 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 的标准输入中。
如果那是您的完整脚本,您可以省略 gimp -i
.
之后的 &
杀死并重新启动 Gimp
Would be even better if I could close gimp instance if it's not used for long enough and start again when it's needed.
这比仅使用 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。
这很天真,但我会试一试。
我想从 bash 和 gimp -i -b - &
启动 gimp,然后在无限循环中读取 dbus 信号,然后从这些信号获得的 post 数据返回到我启动的 gimp。 gimp -i -b -
启动命令行 gimp 并等待用户输入,如 gnuplot 等。但是在命令执行后是否可以从 bash 访问其标准输入?
理想情况下,我想要这样的东西工作:
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 而无需编写一些守护程序应用程序?
简单的解决方案
你可以给我们一个简单的管道。将发送部分脚本的命令包装到一个函数中,并在将其输出通过管道传输到 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 的标准输入中。
如果那是您的完整脚本,您可以省略 gimp -i
.
&
杀死并重新启动 Gimp
Would be even better if I could close gimp instance if it's not used for long enough and start again when it's needed.
这比仅使用 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。