捕获bash中“docker stop”的信号

vtwuwzda  于 2023-01-25  发布在  Docker
关注(0)|答案(4)|浏览(155)

我在一个Docker容器中有一个入口点脚本,看起来如下所示:

#!/bin/bash

echo starting up

function shut_down() {
    echo shutting down

    pid=$(ps -e | grep myapp | awk '{print $1}')
    kill -SIGTERM $pid  
    exit
}

trap "shut_down" SIGKILL SIGTERM SIGHUP SIGINT EXIT

/opt/myapp

我不知道如何捕获通过在容器上运行docker stop发送的信号,当交互运行时,ctrl+c将按预期触发它,但docker stop命令只等待10秒超时,并退出而不进入shut_down函数
如何在bash中捕获docker stop发送的信号以进行一些清理?

ldioqlga

ldioqlga1#

老问题了,但这个问题很有用:

#!/bin/bash

echo starting up

exec /opt/myapp

详情请看这里:https://akomljen.com/stopping-docker-containers-gracefully/

ymzxtsji

ymzxtsji2#

看看this,可能会很有启发性:-)

    • 更新日期:**

@nick-humrich在这里,这是我的蹩脚副本和过去(信贷去原作者https://github.com/lgierth

#!/bin/bash

function ensure_started_container {
  exists=`docker ps -q | grep $1`
  if [ "$?" = "0" ] ; then
    echo "[docker-exec] skipping docker start, already started"
  else
    output=`docker start "$1"`
    echo "[docker start] $output"
  fi
  running=1
}

function setup_signals {
  cid="$1"; shift
  handler="$1"; shift
  for sig; do
    trap "$handler '$cid' '$sig'" "$sig"
  done
}

function handle_signal {
  echo "[docker-exec] received $2"
  case "$2" in
    SIGINT)
      output=`docker stop -t 5 "$1"`
      echo "[docker stop] $output"
      running=0
      ;;
    SIGTERM)
      output=`docker stop -t 5 "$1"`
      echo "[docker stop] $output"
      running=0
      ;;
    SIGHUP)
      output=`docker restart -t 5 "$1"`
      echo "[docker restart] $output"

      # restart logging
      docker attach "$1" &
      kill "$logger_pid" 2> /dev/null
      logger_pid="$!"
      ;;
  esac
}

running=0

setup_signals "$1" "handle_signal" SIGINT SIGTERM SIGHUP

ensure_started_container "$1"

docker attach "$1" &
logger_pid="$!"

while true; do
  if [ "$running" = "1" ]; then
    sleep 1
  else
    break
  fi
done

exit_code=`docker wait "$1"`
exit "$exit_code"
siv3szwd

siv3szwd3#

从Docker 1.9开始,您可以在Dockerfile中使用STOPSIGNAL指令:

STOPSIGNAL signal

STOPSIGNAL设置将发送到容器以退出的系统调用信号。该信号可以是与内核的syscall表中的位置匹配的有效无符号数字,例如9,或者是SIGNAME格式的信号名称,例如SIGKILL。
图片来源:https://docs.docker.com/engine/reference/builder/#stopsignal

3zwjbxry

3zwjbxry4#

在我的例子中,简单地设置一个陷阱是不起作用的,我必须将进程设置为后台来捕捉信号,否则信号会传到启动的进程本身。
起始脚本的最后一行是:

sudo -H -u "$uid" sh -c "myserviced"

我用下面的代码替换了这一行:

shutdown_myservice() {
  set +e
  echo "[SHUTDOWN] Shutting down myservice"
  sudo -u "$uid" myservicecmd -c Shutdown
  echo "[SHUTDOWN] sent. $?"
  wait $dpid  # make sure the process terminated and not just started stopping
  echo "[SHUTDOWN] down. $?"
  return 0
}

trap "shutdown_myservice" HUP INT QUIT TERM USR1

# here, start the process in BACKGROUND
sudo -H -u "$uid" sh -c "myserviced" &
dpid=$!
wait $dpid

这样,“焦点”就不在守护进程上了。相反,它在启动脚本上。我看起来只有“焦点”进程(前台进程)才能得到信号。

相关问题