首页 > 解决方案 > 在入口点脚本中执行后如何清理临时文件?

问题描述

我正在尝试编写自己的 mariadb docker 映像。我想在容器启动后(之后exec mysqld)执行一些 sql 语句。但是我发现mysqld --init-file选项对我的情况很有用。所以我的入口点脚本如下所示。

Dockerfile

FROM alpine:edge

RUN set -ex \
    && apk add mariadb mariadb-client \
    && mkdir -p /run/mysqld \
    && chown -R mysql:mysql /run/mysqld \
    && ln -snf /usr/lib/mariadb /usr/lib/mysql \
    && mysql_install_db --user=mysql --skip-name-resolve --auth-root-authentication-method=socket --auth-root-socket-user=root --force --rpm --skip-test-db

   COPY entrypoint.sh /
   ENTRYPOINT ["/entrypoint.sh"]
   EXPOSE 3306

   CMD ["mysqld"]

入口点.sh

#!/bin/sh

set -ex
{
    echo  "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
    echo  "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
    echo  "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld-init.sql


exec $@ --init-file="/tmp/mysqld-init.sql"

如您所见,临时初始化文件包含一些敏感信息。我想在执行exec $@ --init-file="/tmp/mysqld-init.sql".

现在我想到了两个想法。一种是为临时 sql 命令创建命名管道 (FIFO) 文件或使用 trap 命令。

想法一

但是这里的问题是一个不必要的子后台进程在容器上继续运行,因为我使用了 process control operator &。但是我徒劳无功,我该如何退出该过程。

if [ ! -p "/tmp/mysqld.init" ]; then
    mkfifo /tmp/mysqld.init
fi

{
    echo  "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
    echo  "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
    echo  "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld.init &

exec $@ --init-file="/tmp/mysqld.init"

想法2

执行命令时使用陷阱命令并清理临时文件exec。但我不知道如何捕捉 exec 信号。

trap cleanup "the exec signal"

cleanup()
{
  echo "Caught Signal ... cleaning up."
  rm -rf /tmp/mysqld-init.sql
  echo "Done cleanup ... quitting."
  exit 1
}
  set -ex
{
    echo  "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
    echo  "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
    echo  "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > /tmp/mysqld-init.sql

exec $@ --init-file="/tmp/mysqld.init"

标签: mysqldockernamed-pipesentry-pointbash-trap

解决方案


我认为这trap是最好的解决方案

function interrupt(){

    local dir=$1
    [ -e ${dir} ] && rm -rf ${dir}
    exit 128
}
TMP_DIR=$(mktemp -d /tmp/entrypoint.XXXX)
trap "interrupt ${TMP_DIR}" SIGINT SIGTERM
trap "rm -rf ${TMP_DIR}" EXIT

set -ex
{
    echo  "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';"
    echo  "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};"
    echo  "GRANT ALL ON ${MYSQL_DATABASE}.* TO '${MYSQL_USER}'@'%';"
} > ${TMP_DIR}/mysqld-init.sql

exec $@ --init-file="${TMP_DIR}/mysqld-init.sql"

推荐阅读