问题
kill 命令再次执行时会导致以下错误。
pkill -9 nodeos or kill -9 {pid} database dirty flag set (likely due to unclean shutdown): replay required
当重新运行nodeos时,必须使用--replay-blockchain命令才能重建系统数据。
测试
下面是How do I stop nodeos gracefully? · Issue #4301 · EOSIO/eos · GitHub总结的停止nodes的测试结果
This appears to be two different issues. Startup after a crash or ungraceful shutdown nearly always fails due to corruption of the boost shared memory cache of the in-memory database. --resync is required to clean up the mess. For normal shutdown, never kill with -9. Always use either the default (no argument) signal (which is SIGTERM) or SIGINT. Numerically, those are 15 and 2, respectively. pkill nodeos | Safe pkill -15 nodeos | Safe pkill -2 nodeos | Safe pkill -TERM nodeos | Safe pkill -SIGTERM nodeos | Safe pkill -INT nodeos | Safe pkill -SIGINT nodeos | Safe pkill -9 nodeos | Not Safe pkill -KILL nodeos | Not Safe pkill -SIGKILL nodeos | Not Safe The core dump is a different problem. That looks like a corrupted network packet, specifically a signed_block_summary. Summary messages are being eliminated from the protocol, so this particular error will no longer be possible soon.
总结
简单的安全停止进程的命令:
pkill nodeos
参考自:github
场景2:docker
安全方法
- 如果nodeos运行子docker容器内,根据上面的测试,可以知道下面的方法是安全的
docker kill -s SIGTERM [nodeos容器名]
- docker exec pkill nodeos 也是安全的
docker kill -s SIGTEM是可靠的
默认情况下,docker kill命令不会给容器中的应用程序有任何gracefully shutdown的机会。它会直接发出SIGKILL的系统信号,以强行终止容器中程序的运行.
# docker kill --help Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...] Kill one or more running containers Options: -s, --signal string Signal to send to the container (default "KILL")
但是可以通过-s选项
docker kill -s 信号名 【容器名】 docker kill -s SIGTERM mycontainer
docker stop-不可靠的
在docker stop命令执行的时候,会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认的10秒,会继续发送SIGKILL的系统信号强行kill掉进程。在容器中的应用程序,可以选择忽略和不处理SIGTERM信号,不过一旦达到超时时间,程序就会被系统强行kill掉,因为SIGKILL信号是直接发往系统内核的,应用程序没有机会去处理它。在使用docker stop命令的时候,我们唯一能控制的是超时时间,比如设置为20秒超时:
# docker stop --help Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] Stop one or more running containers Options: -t, --time int Seconds to wait for stop before killing it (default 10)
-t:关闭容器的限时,如果超时未能关闭则用kill强制关闭,默认值10s,这个时间用于容器的自己保存状态
docker restart
关闭阶段与docker stop机制式样的的。
源码分析
在eos项目的文件\eos\libraries\appbase\application.cpp中可以看到,nodeos可以通过3个信号SIGINT, SIGTERM, SIGPIPE来安全的关闭程序。我们一般用SIGTERM就好。
void application::setup_signal_handling_on_ios(boost::asio::io_service& ios) { std::shared_ptr<boost::asio::signal_set> ss = std::make_shared<boost::asio::signal_set>(ios, SIGINT, SIGTERM, SIGPIPE); wait_for_signal(ss); }