在 Docker 映像中运行xfvb。此代码有一个信号处理程序,当 Docker 容器收到 SIGTERM 时,该处理程序应在 SIGTERM 上正常退出(例如通过取消 google cloud run 作业)。
我的进程似乎没有接收和信号。我已经使用 tini 作为 Dockerfile 中的入口点来处理信号,正如基本上所有其他与此相关的问题中所建议的那样。
这是我正在运行的一些代码来调试行为:
const sleep = (millis: number): Promise<void> =>
new Promise((resolve) => setTimeout(resolve, millis));
export const main = async (): Promise<void> => {
process.on("SIGTERM", () => {
console.log("Received sigterm")
process.exit(1)
})
console.log({pid: process.pid})
let i = 0
while (true) {
i++;
console.log({i}, "sleeping")
await sleep(1000)
}
}
这是我的
Dockerfile
:
# ...More setup code to install the typescript code
COPY src ./src
RUN npm i && pnpm build
ENTRYPOINT ["/tini", "--"]
CMD ["xvfb-run", '-s "-screen 0 1920x1080x8"', "node", "src"]
我现在运行以下命令来使用 SIGTERM 启动和终止图像:
docker build -t debug:signals .
docker run --rm -t --name killme debug:signals
docker kill --signal=SIGTERM killme
我只得到这样的输出,请注意有关捕获的 sigterm 的日志行丢失了:
{ pid: 20 }
{ i: 1 } sleeping
{ i: 2 } sleeping
{ i: 3 } sleeping
{ i: 4 } sleeping
{ i: 5 } sleeping
{ i: 6 } sleeping
一旦收到没有日志的 SIGTERM,它就会停止。
如何将信号传递给 xfvb 内运行的节点进程?
您需要自己构建信号转发,xfvb 不会为您做这件事。 为此,创建一个在后台启动 xvfb 的脚本,捕获信号并将其转发给 xfvb 进程的子进程:
#!/bin/bash
# Start the process with a virtual x server
xvfb-run -s "-screen 0 1920x1080x8" "$@" &
# Get the PID of the background process of the x server
CHILD_PID=$!
forward_signal() {
# $1 is the signal that is forwarded
# pgrep -P gives me processes which have the xfvb-run as a parent process
kill -"$1" $(pgrep -P $CHILD_PID)
}
# Trap the signals you need and forward them
trap 'forward_signal SIGTERM' SIGTERM
# Wait for the xfvb-run process to finish
wait $CHILD_PID
使其可执行并将其添加到您的 Dockerfile 中:
# ...
ENTRYPOINT ["/tini", "--"]
CMD ["./forwardSignals.sh", "node", "src"]
您现在将通过运行 docker 命令获得所需的输出:
{ pid: 17 }
{ i: 1 } sleeping
{ i: 2 } sleeping
{ i: 3 } sleeping
{ i: 4 } sleeping
Received sigterm