bash - 捕获 docker 信号并停止 bash 中的进程不起作用

标签 bash docker

我已经阅读并尝试过这个

我无法优雅地停止我的 docker 容器,容器只是停止并杀死里面的所有内容,而不是运行我的陷阱处理程序,我已经尝试解决这个问题一年或更长时间了。

这是我的入口点

ENTRYPOINT ["/home/sdtdserver/user.sh", "/home/sdtdserver/install.sh"]

这是做准备工作然后继续其他的脚本之一,user.sh

    #!/bin/bash
    exit_handler() {
            # Execute the  shutdown commands
            echo "[INFO] Stopping 7 Days To Die Server" >> /home/sdtdserver/log/console/sdtdserver-console.log
            su-exec sdtdserver /home/sdtdserver/sdtdserver stop
            exit
    }
    
    set -eu
    
    # Print info
    echo "
            =======================================================================
            USER INFO:
    
            UID: $PUID
            GID: $PGID
    
            MORE INFO:
    
            If you have permission problems remember to use same user UID and GID.
            Check it with "id" command
            If problem persist check:
            https://github.com/vinanrra/Docker-7DaysToDie/blob/master/README.md
            =======================================================================
    "
    
    # Set user and group ID to sdtdserver user
    groupmod -o -g "$PGID" sdtdserver  > /dev/null 2>&1
    usermod -o -u "$PUID" sdtdserver  > /dev/null 2>&1
    
    # Locale, Timezone
    localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 && \
    ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone
    
    # Apply owner to the folder to avoid errors
    chown -R sdtdserver:sdtdserver /home/sdtdserver
    
    # Start cron
    service cron start
    
    # Change user to sdtdserver
    su-exec sdtdserver "$@"
    
    # Trap specific signals and forward to the exit handler
    trap exit_handler SIGTERM
    
    # Keep script alive to trap SIGTERM
    while true; do
            sleep 10
    done

我认为我的问题在这里:su-exec sdtdserver "$@"- 第 43 行

我正在使用 su-exec 执行交换用户并以其他用户身份执行下一个脚本,也许这就是问题所在,我也一直在考虑将 user.sh 脚本移动到该脚本所在的位置在启动时执行,不使用 Dockerfile 中的入口点,而是交换到我的其他脚本 install.sh甚至删除 su-exec 的使用并重新格式化一个脚本中的所有内容(我不喜欢这个想法)

#!/bin/bash
rootDir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
scriptsDir="${rootDir}/scripts"

# Show log function
show_log () {
   i="0"
      # -F = --follow=name --retry
      tail -F /home/sdtdserver/log/console/sdtdserver-console.log
}

test_alert () {
   if [ "${TEST_ALERT,,}" == 'yes'  ]; then
      source $scriptsDir/server_alerts.sh
   fi
}

# Check requeriments

# Check if script is missing
if [ ! -f sdtdserver ]; then
   source $scriptsDir/check_script.sh
fi

# Check if server have been installed
if [ ! -f serverfiles/DONT_REMOVE.txt ]; then
   source $scriptsDir/first_install.sh
fi

# Crontab
echo "# Crontab file" > crontab.txt

if [ "${BACKUP,,}" == 'yes'  ]; then
   source $scriptsDir/crontab/backup.sh
fi

if [ "${MONITOR,,}" == 'yes'  ]; then
   source $scriptsDir/crontab/monitor.sh
fi

echo "# Don't remove the empty line at the end of this file. It is required to run the cron job" >> crontab.txt

crontab crontab.txt

rm crontab.txt

# Use of case to avoid errors if used wrong START_MODE
case $START_MODE in
   0)
      exit
   ;;
   1)
      source $scriptsDir/server_start.sh
      test_alert
      show_log
   ;;
   2)
      source $scriptsDir/server_update.sh
      exit
   ;;
   3)
      source $scriptsDir/server_update.sh
      source $scriptsDir/server_start.sh
      test_alert
      show_log
   ;; 
   4)
      source $scriptsDir/server_backup.sh
      exit
   ;;
   *)
      source $scriptsDir/check_startMode.sh
      exit
   ;;
esac

这是容器内的顶级命令:

TOP-Command

这是我正在进行测试的 GitHub 分支:fix-exit

首先感谢每个试图帮助我的人,其次我只是不想复制和粘贴代码,我想了解为什么不起作用,因为这就是我遇到的问题,我一无所知,那就是为什么我无法修复它,即使是文档也是如此。

最佳答案

问题是我没有异步运行脚本,并且 bash 正在等待结束 install.sh 末尾的 tail 命令(这是“无尽的”),这是更改的代码部分:

# Change user to sdtdserver
su-exec sdtdserver bash /home/sdtdserver/install.sh &
# If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes.
# When bash is waiting for an asynchronous command via the wait builtin,
# the reception of a signal for which a trap has been set will cause the 'wait' builtin to return immediately with an exit status greater than 128,
# immediately after which the trap is executed.
wait $!

另外,这个人也有同样的问题,但我不知道是尾部的问题。

SIGTERM signal not caught when the last process is tail

关于bash - 捕获 docker 信号并停止 bash 中的进程不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70770104/

相关文章:

linux - 守护进程不会杀死正在从命名管道读取的 child

linux - Crosstool-ng python 错误

bash - 如何在 Bash 中同时循环两个文件(一个文本文件,一个json文件)?

node.js - Jenkins 内的 Docker 代理 - npm "cannot find module"

docker - 如何在docker容器文件夹中授予文件夹权限

docker - 没有找到编辑器(编辑器路径 =/usr/bin/editor)正在运行 visudo

linux - 能够在 bash SED 中使用变量

bash - if [[ $# -ge 1 ]] 在 shell 脚本中是什么意思

docker - 在 HTTPS 上运行 docker 服务

maven - 如何使用fabric8-maven-plugin标记图像?