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 stop
和kubectl delete
将TERM
信号发送到具有容器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
andUSR2
are typically used to print statistics or status informationUSR1
和USR2
通常用于打印统计信息或状态信息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 beforeKILL
-ing your PID no. 1.docker stop
仅等待十秒钟,然后KILL
您的PID号。 1。kubectl delete
defaults to 30 seconds before sending theKILL
signal and can be configured withterminationGracePeriodSeconds
.
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 alltmux
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 asENTER
for screenstuff
:screen -X stuff $(echo -e "quit\r\n")
.
echo -e "\r\n"
可以如使用ENTER
对于屏幕stuff
:screen -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
(inbash
) sends the signal to the first background job
kill -TERM %1
(在bash
)将信号发送到第一个后台作业exec myapp
will makemyapp
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
orsh
as entrypoint script (if any). They automatically clean up their child processes. K.I.S.S.
最好只使用bash
或sh
作为入口点脚本(如果有)。 他们自动清理其子进程。 吻 - 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.
- You can easily pass signals to sub-processes or send commands to your
tmux
andscreen
sessions.
您可以轻松地将信号传递到子流程,或将命令发送到tmux
和screen
会话。
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之类的人和伟大文章的启发。
- Screen: https://man7.org/linux/man-pages/man1/screen.1.html 屏幕: https : //man7.org/linux/man-pages/man1/screen.1.html
- tmux: https://man7.org/linux/man-pages/man1/tmux.1.html tmux: https : //man7.org/linux/man-pages/man1/tmux.1.html
- Signals and traps: https://www.tutorialspoint.com/unix/unix-signals-traps.htm 信号和陷阱: https : //www.tutorialspoint.com/unix/unix-signals-traps.htm
- kill [%]PID: https://stackoverflow.com/questions/14197470/how-does-trap-kill-work-in-bash-on-linux 杀死[%] PID: https : //stackoverflow.com/questions/14197470/how-does-trap-kill-work-in-bash-on-linux
tmux docker