tmux docker_即使在tmux或屏幕中运行时也可以正常关闭docker应用

淳于恺
2023-12-01

tmux docker

信号如何工作(How Signals Work)

First, the simple facts: docker stop as well as kubectl delete send a TERM signal to the process with PID 1 of the container. If you run multiple containers in a Kubernetes pod, each of them gets the signal.

首先,简单的事实: kubectl delete docker stopkubectl deleteTERM信号发送到具有容器PID 1的进程。 如果您在Kubernetes容器中运行多个容器,则每个容器都会收到信号。

The TERM signal tells the process to terminate, and most apps handle it just like one would expect: They shut down.

TERM信号告诉该过程终止,大多数应用程序都按照预期进行处理:它们已关闭。

But there are other useful signals typically used by apps and signals you can use for your own purposes really easily in your entrypoint.sh.

但是,应用程序通常还会使用其他有用的信号,并且您可以在entrypoint.sh非常轻松地将其用于自己的目的。

  • HUP is typically used to signal a program to reload configuration

    HUP通常用于发信号通知程序重新加载配置

  • USR1 and USR2 are typically used to print statistics or status information

    USR1USR2通常用于打印统计信息或状态信息

  • INT is sent when you hit C-c in the terminal to interrupt the process

    当您在终端中按Cc键以中断过程时,将发送INT

When you run your actual app in a child process or tmux or Screen session, you can trap the signal and send custom commands to your app to shut it down, or to print statistics or its status.

在子进程,tmux或Screen会话中运行实际应用程序时,可以捕获信号并将自定义命令发送到您的应用程序以将其关闭,或打印统计信息或其状态。

#!/bin/bashtrap 'myapp --reload' HUP
trap 'tmux send-keys status C-m' USR1
trap 'screen -X stuff $(echo -e "stats\r\n")' USR2

When you start your app with exec in your entrypoint.sh, then things look different. Using exec causes the process to take over the current process, which means your entrypoint.sh no longer runs. It won’t even execute the rest of the script. This also means that any trap you have set in your entrypoint.sh no longer exists. Your app must take care of signal handling.

当您在entrypoint.sh使用exec启动应用程序时,情况会有所不同。 使用exec会使进程接管当前进程,这意味着您的entrypoint.sh不再运行。 它甚至不会执行脚本的其余部分。 这也意味着您在entrypoint.sh设置的任何trap不再存在。 您的应用必须注意信号处理。

须知 (Things to Know)

  • docker stop waits only ten seconds before KILL-ing your PID no. 1.

    docker stop仅等待十秒钟,然后KILL您的PID号。 1。

  • kubectl delete defaults to 30 seconds before sending theKILL signal and can be configured with terminationGracePeriodSeconds.

    kubectl delete默认值是发送KILL信号之前的30秒,并且可以使用terminationGracePeriodSeconds进行配置。

  • tmux send-keys allows sending special characters and is more convenient to automate: tmux send-keys Hello C-m My name is DrPsychick C-m.

    tmux send-keys允许发送特殊字符,并且更易于自动化: tmux send-keys Hello Cm My name is DrPsychick Cm

  • tmux kill-server is the fast way to kill all tmux sessions.

    tmux kill-server是杀死所有tmux会话的快速方法。

  • screen -X stuff "..." lets you directly input data into the screen stdin as if you had typed it.

    screen -X stuff "..."使您可以直接将数据输入到屏幕标准输入中,就像您已经键入了一样。

  • echo -e "\r\n" can be used as ENTER for screen stuff : screen -X stuff $(echo -e "quit\r\n").

    echo -e "\r\n"可以如使用ENTER对于屏幕stuffscreen -X stuff $(echo -e "quit\r\n")

  • kill -TERM 0 sends the signal to all processes in the group (all children and the parent itself).

    kill -TERM 0将信号发送到组中的所有进程(所有子进程和父进程本身)。

  • kill -TERM %1 (in bash) sends the signal to the first background job

    kill -TERM %1 (在bash )将信号发送到第一个后台作业

  • exec myapp will make myapp take over PID no. 1, and it must handle signals itself.

    exec myapp将使myapp接管PID号。 1,它必须自己处理信号。

边干边学 (Learning by Doing)

What I learned:

我学到的是:

  • It's best to simply use bash or sh as entrypoint script (if any). They automatically clean up their child processes. K.I.S.S.

    最好只使用bashsh作为入口点脚本(如果有)。 他们自动清理其子进程。 吻

  • The alternative is launching a binary directly that handles the signals, which would be the case for modern services, but it then should also “reap” zombie children.

    另一种选择是直接启动一个二进制文件来处理信号,现代服务就是这种情况,但随后它也应该“收获”僵尸孩子。
  • Use tmux if you can’t avoid running an app that requires a terminal.

    如果无法避免运行需要终端的应用程序,请使用tmux

  • trap is fast to implement and easy to understand. It can call functions defined in the script, which makes it quite powerful. What else do you need?

    trap易于实现且易于理解。 它可以调用脚本中定义的函数,因此功能非常强大。 你还需要什么?

Here’s my small Docker image repo to play with traps and signals. It includes examples to run it with docker as well as kubectl (running minikube in my case).

这是我的小型Docker镜像存储库,用于处理陷阱和信号。 它包括实例与运行它docker以及kubectl (运行minikube在我的情况)。

It runs a tmux session as well as a screen session, which both write to a shared log file, which is tail-ed to print it to stdout. Every common signal is trapped and triggers different actions.

它运行一个tmux会话以及一个screen会话,这两个会话均写入共享日志文件,该文件tail对齐以将其打印到stdout。 每个公共信号都会被捕获并触发不同的动作。

概要 (Summary)

  • You can react to TERM in any container, and in a Kubernetes environment, you can configure the grace period to ensure that your app shuts down cleanly before getting killed.

    您可以在任何容器中对TERM做出React,在Kubernetes环境中,您可以配置宽限期以确保您的应用在被杀死之前能够干净关闭。

  • You can react to other signals and trigger custom actions or commands in your app.

    您可以对其他信号做出React,并在应用程序中触发自定义操作或命令。
  • You can easily pass signals to sub-processes or send commands to your tmux and screen sessions.

    您可以轻松地将信号传递到子流程,或将命令发送到tmuxscreen会话。

Thank you for your time!

感谢您的时间!

进一步阅读 (Further Reading)

Why you should stick to bash as entrypoint.sh:

为什么要坚持bash作为entrypoint.sh

Use my_init to translate signals, from this article:

使用my_init转换信号,来自本文:

my_init: https://github.com/phusion/baseimage-docker/blob/rel-0.9.19/image/bin/my_init

my_init: https my_init: //github.com/phusion/baseimage-docker/blob/rel-0.9.19/image/bin/my_init

Inspired by people like Marco Pracucci and great articles.

受到Marco Pracucci之类的人和伟大文章的启发。

翻译自: https://medium.com/better-programming/shut-down-docker-apps-gracefully-even-when-running-in-tmux-or-screen-41e68ff17187

tmux docker

 类似资料: