diff --git a/greatsql/ADD/ccmd b/greatsql/ADD/ccmd new file mode 100755 index 0000000..476b68a --- /dev/null +++ b/greatsql/ADD/ccmd @@ -0,0 +1,100 @@ +#!/bin/bash + +################################################## +# Mount file # +# - /etc/my.cnf # +# Mount dir # +# - LOG_DIR # +# - DATA_DIR # +# - BINLOG_DIR # +################################################## + +set -euo pipefail +export LANG=en_US.UTF-8 +export LD_PRELOAD=/usr/lib64/libjemalloc.so +export THP_SETTING= +trap Quit EXIT + +PIDS= +GOT_SIGTERM= +LOG_DIR='/var/log/mysql' +DATA_DIR='/var/lib/mysql' +BINLOG_DIR='/var/lib/mysql-bin' +SOCK_FILE='/run/mysqld/mysqld.sock' +PID_FILE='/run/mysqld/mysqld.pid' +INIT_FLAG= + +function Print { + local file=/dev/null + [ '-f' = "$1" ] && file=$2 && shift && shift + date +"[%F %T] $*" | tee -a $file +} + +function Quit { + Print killing greatsql ... + mysqladmin shutdown || true + while :; do + pkill -f mysqld && Print killing greatsql ... || break + sleep 1 + done + Print Container stopped. + test -n "$GOT_SIGTERM" +} + +function Init { + echo never > /sys/kernel/mm/transparent_hugepage/enabled \ + && echo never > /sys/kernel/mm/transparent_hugepage/defrag \ + && THP_SETTING=never \ + || Print Failed to disable THP, consider privileged container. + rm -f ${SOCK_FILE}* ${PID_FILE} + chown -R mysql:mysql $LOG_DIR $BINLOG_DIR $DATA_DIR + chmod 0750 $LOG_DIR + if [ ! -d "$DATA_DIR/mysql" ]; then + Print Initing greatsql db files ... + mysqld_pre_systemd + INIT_FLAG=1 + fi +} + +function ImportInitSql { + local sql_file= sql_files= + mysql -e "CREATE USER docker@localhost IDENTIFIED BY 'China_19\$(10)!'" + mysql -e "GRANT SHUTDOWN ON *.* TO docker@localhost" + if sql_files="$(ls $LOG_DIR/init_sql/*.sql 2>/dev/null)"; then + Print Importing the sql files ... + for sql_file in $sql_files; do + Print Importing $sql_file ... + mysql < $sql_file + done + Print Imported all sql files successfully. + fi +} + +function StartProc { + mysqld & + PIDS="$PIDS $!" + while sleep 1; do + [ -e $SOCK_FILE ] && break || echo -n . + [ ! -e /proc/$! ] && echo && Print unexpected error! && exit + done + echo + [ -z "$INIT_FLAG" ] || ImportInitSql + Print GreatSQL is ready for connections. +} + +function Main { + local pid= + Print Starting greatsql ... + Init + StartProc + trap "GOT_SIGTERM=1; Print Got SIGTERM ..." SIGTERM + while [ -z "$GOT_SIGTERM" ] && sleep 1; do + for pid in $PIDS; do + [ ! -e /proc/$pid ] && Print Unexpected error! && exit + done + done +} + +# Start here +Main + diff --git a/greatsql/Dockerfile-greatsql8 b/greatsql/Dockerfile-greatsql8 new file mode 100644 index 0000000..fe2f4be --- /dev/null +++ b/greatsql/Dockerfile-greatsql8 @@ -0,0 +1,107 @@ +ARG ARCH +FROM harbor.colben.cn/general/rocky$ARCH:8 +MAINTAINER Colben colbenlee@gmail.com +ARG BUNDLE_FILE +ADD --chown=root:root /ADD/ /opt/ +RUN echo -e 'fs.file-max = 1000000\n\ +net.core.somaxconn = 32768\n\ +net.ipv4.tcp_syncookies = 0\n\ +vm.overcommit_memory = 1\n\ +' >> /etc/sysctl.conf \ + && echo -e '\n\ +mysql soft nofile 65535\n\ +mysql hard nofile 65535\n\ +mysql soft stack 32768\n\ +mysql hard stack 32768\n\ +mysql soft nproc 65535\n\ +mysql hard nproc 65535\n\ +' >> /etc/security/limits.conf \ + && echo -e '[epel]\n\ +name=Extra Packages for Enterprise Linux $releasever - $basearch\n\ +baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/$releasever/Everything/$basearch\n\ +enabled=1\n\ +gpgcheck=0\n\ +' > /etc/yum.repos.d/epel.repo \ + && dnf makecache \ + && dnf -y install xz pkg-config perl libaio-devel numactl-devel numactl-libs net-tools openssl openssl-devel jemalloc jemalloc-devel perl-Data-Dumper perl-Digest-MD5 python2 perl-JSON perl-Test-Simple \ + && curl -LO http://10.11.0.1:10080/$BUNDLE_FILE \ + && tar xf $BUNDLE_FILE -C /tmp/ \ + && rm -f /tmp/greatsql-devel* /tmp/greatsql-mysql-router-* \ + && rpm -ivh /tmp/greatsql-*.rpm \ + && ln -s /usr/bin/mysql /usr/bin/greatsql \ + && ln -s /usr/bin/mysqldump /usr/bin/greatsqldump \ + && rm -rf /usr/sbin/mysqld-debug \ + /var/cache/yum \ + /var/lib/yum \ + /var/lib/rpm \ + /var/log/* \ + /etc/my.cnf.d \ + $BUNDLE_FILE \ + /tmp/greatsql-*.rpm \ + && mkdir -p /var/log/mysql \ + /var/lib/mysql-bin \ + /etc/mysql \ + && chown -R mysql:mysql \ + /var/log/mysql \ + /var/lib/mysql-bin \ + && chmod 0750 /var/log/mysql \ + && sed -i -e 's,--initialize,&-insecure,g' \ + -e 's,/usr/sbin/mysqld ,&--defaults-file=/etc/mysql/my.cnf ,g' \ + /usr/bin/mysqld_pre_systemd \ + && echo -e '[mysqld]\n\ +mysqlx = OFF\n#\ +default-time-zone = "+8:00"\n\ +lock-wait-timeout = 3600\n\ +open-files-limit = 65535\n\ +back-log = 1024\n\ +max-connections = 512\n\ +lock-wait-timeout = 3600\n\ +open-files-limit = 65535\n\ +back-log = 1024\n\ +max-connections = 512\n\ +max-connect-errors = 1000000\n\ +table-open-cache = 1024\n\ +table-definition-cache = 1024\n\ +thread-stack = 512K\n\ +sort-buffer-size = 4M\n\ +join-buffer-size = 4M\n\ +read-buffer-size = 8M\n\ +read-rnd-buffer-size = 4M\n\ +bulk-insert-buffer-size = 64M\n\ +thread-cache-size = 768\n\ +interactive-timeout = 600\n\ +wait-timeout = 600\n\ +tmp-table-size = 32M\n\ +max-heap-table-size = 32M\n\ +max-allowed-packet = 64M\n\ +net-buffer-shrink-interval = 180\n\ +sql-generate-invisible-primary-key = ON\n\ +' > /etc/my.cnf \ + && echo -e '[client]\n\ +socket = /run/mysqld/mysqld.sock\n\ +\n\ +[mysql]\n\ +prompt = "[GreatSQL:\u@\d]>\_"\n\ +\n\ +[mysqld]\n\ +user = mysql\n\ +datadir = /var/lib/mysql\n\ +socket = /run/mysqld/mysqld.sock\n\ +pid-file = /run/mysqld/mysqld.pid\n\ +log-timestamps = SYSTEM\n\ +secure-log-path = /var/log/mysql\n\ +log-error = /var/log/mysql/error.log\n\ +log-error-suppression-list = MY-013360\n\ +character-set-server = utf8mb4\n\ +default-storage-engine = innodb\n\ +slow-query-log = TRUE\n\ +slow-query-log-file = /var/log/mysql/slow.log\n\ +authentication-policy = mysql_native_password\n\ +lower-case-table-names = 1\n\ +\n\ +[mysqladmin]\n\ +user = docker\n\ +password = China_19$(10)!\n\ +' > /etc/mysql/my.cnf +CMD ["/opt/ccmd"] + diff --git a/greatsql/README.md b/greatsql/README.md new file mode 100644 index 0000000..fe26996 --- /dev/null +++ b/greatsql/README.md @@ -0,0 +1,19 @@ +# 构建 greatsql 8.0 镜像 + +## 定制 +- 安装 greatsql 8.0 +- 固定一些常用配置 +- 第一次启动时,会执行如下操作 + - 初始化数据目录 + - 自动创建一个只有 shutdown 权限的普通用户,该用户用于优雅停止 greatsql,__不要修改该用户任何信息__ + - 自动执行 {mysql-log}/init_sql/ 下的 xxxx.sql 文件 + +## 外挂目录和文件 +- /etc/my.cnf: mysql 配置文件 +- /var/lib/mysql: mysql 数据目录 +- /var/lib/mysql-bin: mysql binlog 目录 +- /var/log/mysql: mysql 日志目录 + +## 案例 +- 参考 mysql + diff --git a/greatsql/greatsql8.sh b/greatsql/greatsql8.sh new file mode 100755 index 0000000..4d08b3c --- /dev/null +++ b/greatsql/greatsql8.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +#========================================= +# Author : colben +#========================================= + +set -euo pipefail +export LANG=en_US.UTF-8 + +[ 'x86_64' == "$(uname -m)" ] && ARCH='' || ARCH="-$(uname -m)" +ROOT_DIR="$(cd $(dirname $0) && pwd)" +IMAGE="harbor.colben.cn/general/greatsql$ARCH:8" +BUNDLE_FILE= + +if [ -t 0 ]; then + function Print { echo -e "\033[36;1m$(date +'[%F %T]')\033[32;1m $*\033[0m"; } + function Warn { echo -e "\033[36;1m$(date +'[%F %T]')\033[33;1m $*\033[0m"; } + function Error { echo -e "\033[36;1m$(date +'[%F %T]')\033[31;1m $*\033[0m"; exit 1; } +else + function Print { echo -e "$(date +'[%F %T INFO]') $*"; } + function Warn { echo -e "$(date +'[%F %T WARN]') $*"; } + function Error { echo -e "$(date +'[%F %T ERROR]') $*"; exit 1; } +fi + +function Quit { + local exitCode=$? + pkill -f '^python2 -m SimpleHTTPServer 10080$' || true + [ 0 -ne $exitCode ] && Error Failed to build or push image! + [ -z "${END:-}" ] && echo && Error Interrupted manually! + Print Succeeded to build and push image. +} + +function YesOrNo { + Warn $* + local sw= + while :; do + read -p '(Yes/No/Quit) ' -n1 sw + [[ "$sw" =~ ^Y|y$ ]] && echo && return 0 + [[ "$sw" =~ ^N|n$ ]] && echo && return 1 + [[ "$sw" =~ ^Q|q$ ]] && echo && exit 0 + [ -n "$sw" ] && echo + done +} + +function Update { + Warn Check files ... + cd /release/RUNTIME + if [ -z "$ARCH" ]; then + BUNDLE_FILE=greatsql-8.0.32-26.1.el8.amd64.rpm-bundle.tar.xz + elif [ '-aarch64' == "$ARCH" ]; then + BUNDLE_FILE=greatsql-8.0.32-26.1.el8.arm64.rpm-bundle.tar.xz + else + Error Unknown arch: $ARCH! + fi + [ -e $BUNDLE_FILE ] || Error Not found $BUNDLE_FILE! + python2 -m SimpleHTTPServer 10080 &>/dev/null & +} + +function Build { + local yn + cd $ROOT_DIR + docker images --format='{{.Repository}}:{{.Tag}}' | grep "^$IMAGE$" \ + && Warn Removing image $IMAGE ... \ + && docker rmi $IMAGE + Warn Building image: $IMAGE ... + docker build --force-rm --build-arg ARCH="$ARCH" --build-arg BUNDLE_FILE="$BUNDLE_FILE" -t $IMAGE -f Dockerfile-greatsql8 . + YesOrNo Push image: $IMAGE? && docker push $IMAGE +} + +function Main { + trap Quit EXIT + Update + Build + END=1 +} + +# Start here +Main + diff --git a/vsftpd/ADD/ccmd b/vsftpd/ADD/ccmd new file mode 100755 index 0000000..c8c57ac --- /dev/null +++ b/vsftpd/ADD/ccmd @@ -0,0 +1,77 @@ +#!/bin/bash + +################################################## +# Mount file # +# - /etc/vsftpd/vsftpd.conf # +# Mount dir # +# - /var/lib/ftp, /home or other data_dir # +# - LOG_DIR # +# ENV # +# - VSFTPD_OPTS # +################################################## + +set -euo pipefail +export LANG=en_US.UTF-8 +trap Quit EXIT + +PIDS= +GOT_SIGTERM= +LOG_DIR='/var/log/vsftpd' +ARGS="${VSFTPD_OPTS:-}" + +function Print { + local file=/dev/null + [ '-f' = "$1" ] && file=$2 && shift && shift + date +"[%F %T] $*" | tee -a $file +} + +function Quit { + Print killing vsftpd ... + while :; do + pkill -f rsync && Print killing vsftpd ... || break + sleep 1 + done + Print Container stopped. + test -n "$GOT_SIGTERM" +} + +function CreateFtpUser { + local kv= + local uid= + local user= + local userList=/etc/vsftpd/user_list + Print Create ftp users ... + : > $userList + grep -q '^anonymous_enable *= *YES' /etc/vsftpd/vsftpd.conf && echo anonymous >> $userList + for kv in $(env | grep '^FTP_USER_[0-9]\+='); do + uid=$(echo $kv | cut -d= -f1 | cut -d_ -f3) + user=$(echo $kv | cut -d= -f2- | cut -d: -f1) + userPass=$(echo $kv | cut -d= -f2-) + id $uid || adduser -D -s /sbin/nologin -u $uid $user + echo "${userPass}" | chpasswd + echo $user >> $userList + done +} + +function StartProc { + Print Starting vsftpd ... + vsftpd /etc/vsftpd/vsftpd.conf $ARGS /etc/vsftpd/vsftpd-sys.conf & + PIDS="$PIDS $!" + Print vsftpd started. +} + +function Main { + local pid= + CreateFtpUser + StartProc + trap "GOT_SIGTERM=1; Print Got SIGTERM ..." SIGTERM + while [ -z "$GOT_SIGTERM" ] && sleep 1; do + for pid in $PIDS; do + [ ! -e /proc/$pid ] && Print Unexpected error! && exit + done + done +} + +# Start here +Main + diff --git a/vsftpd/Demo/README.md b/vsftpd/Demo/README.md new file mode 100644 index 0000000..f2ea543 --- /dev/null +++ b/vsftpd/Demo/README.md @@ -0,0 +1,16 @@ +# 部署 vsftpd + +- 服务器数据盘挂载到 /data/ 目录下 +- 根据实际环境修改 + - docker-compose.yml + +- 创建目录 + ``` + grep '\ /etc/vsftpd/vsftpd-sys.conf + +CMD ["/opt/ccmd"] + diff --git a/vsftpd/README.md b/vsftpd/README.md new file mode 100644 index 0000000..9c19a86 --- /dev/null +++ b/vsftpd/README.md @@ -0,0 +1,15 @@ +# 构建 vsftpd 镜像 + +## 定制 +- 安装 vsftpd + +## 外挂目录和文件 +- /etc/vsftpd/vsftpd.conf: vsftpd 配置文件 +- /var/log/vsftpd: vsftpd 日志目录 +- 数据目录 + * anonymous 用户: /var/lib/ftp + * 其他用户: $HOME 或 local_root + +## 案例 +- [Demo/](Demo/): 部署 vsftpd + diff --git a/vsftpd/vsftpd.sh b/vsftpd/vsftpd.sh new file mode 100755 index 0000000..7c036fd --- /dev/null +++ b/vsftpd/vsftpd.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +#========================================= +# Author : colben +#========================================= + +set -euo pipefail +export LANG=en_US.UTF-8 + +[ 'x86_64' == "$(uname -m)" ] && ARCH='' || ARCH="-$(uname -m)" +ROOT_DIR="$(cd $(dirname $0) && pwd)" +IMAGE="harbor.colben.cn/general/$(basename ${0%.sh})$ARCH:latest" + +if [ -t 0 ]; then + function Print { echo -e "\033[36;1m$(date +'[%F %T]')\033[32;1m $*\033[0m"; } + function Warn { echo -e "\033[36;1m$(date +'[%F %T]')\033[33;1m $*\033[0m"; } + function Error { echo -e "\033[36;1m$(date +'[%F %T]')\033[31;1m $*\033[0m"; exit 1; } +else + function Print { echo -e "$(date +'[%F %T INFO]') $*"; } + function Warn { echo -e "$(date +'[%F %T WARN]') $*"; } + function Error { echo -e "$(date +'[%F %T ERROR]') $*"; exit 1; } +fi + +function Quit { + local exitCode=$? + [ 0 -ne $exitCode ] && Error Failed to build or push image! + [ -z "${END:-}" ] && echo && Error Interrupted manually! + Print Succeeded to build and push image. +} + +function YesOrNo { + Warn $* + local sw= + while :; do + read -p '(Yes/No/Quit) ' -n1 sw + [[ "$sw" =~ ^Y|y$ ]] && echo && return 0 + [[ "$sw" =~ ^N|n$ ]] && echo && return 1 + [[ "$sw" =~ ^Q|q$ ]] && echo && exit 0 + [ -n "$sw" ] && echo + done +} + +function Update { + : +} + +function Build { + local yn + cd $ROOT_DIR + docker images --format='{{.Repository}}:{{.Tag}}' | grep "^$IMAGE$" \ + && Warn Removing image $IMAGE ... \ + && docker rmi $IMAGE + Warn Building image: $IMAGE ... + docker build --force-rm --build-arg ARCH="$ARCH" -t $IMAGE . + YesOrNo Push image: $IMAGE? && docker push $IMAGE +} + +function Main { + trap Quit EXIT + Update + Build + END=1 +} + +# Start here +Main +