feat(database-dump-via-docker-sock): 支持指定容器内执行命令的用户
This commit is contained in:
@@ -12,7 +12,7 @@ print_usage() {
|
|||||||
cat <<EOF_USAGE >&2
|
cat <<EOF_USAGE >&2
|
||||||
Usage: $0 [--socket=PATH] [--api-version=VERSION] --container=NAME \\
|
Usage: $0 [--socket=PATH] [--api-version=VERSION] --container=NAME \\
|
||||||
[--type=postgres|mysql|kingbase] --backup-prefix=PREFIX [--backup-dir=DIR] \\
|
[--type=postgres|mysql|kingbase] --backup-prefix=PREFIX [--backup-dir=DIR] \\
|
||||||
[--mysql-user=USER] [--mysql-password=PASSWORD]
|
[--mysql-user=USER] [--mysql-password=PASSWORD] [--exec-user=NAME]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--socket=PATH Docker Engine unix socket path (default: /var/run/docker.sock)
|
--socket=PATH Docker Engine unix socket path (default: /var/run/docker.sock)
|
||||||
@@ -23,6 +23,7 @@ Options:
|
|||||||
--backup-prefix=PREFIX Backup filename prefix
|
--backup-prefix=PREFIX Backup filename prefix
|
||||||
--mysql-user=USER MySQL user (default: root)
|
--mysql-user=USER MySQL user (default: root)
|
||||||
--mysql-password=PASSWORD MySQL password (optional)
|
--mysql-password=PASSWORD MySQL password (optional)
|
||||||
|
--exec-user=NAME Force a specific user when running commands inside the container
|
||||||
--help Show this help message
|
--help Show this help message
|
||||||
EOF_USAGE
|
EOF_USAGE
|
||||||
}
|
}
|
||||||
@@ -36,6 +37,7 @@ BACKUP_PREFIX=""
|
|||||||
MYSQL_USER="root"
|
MYSQL_USER="root"
|
||||||
MYSQL_PASSWORD=""
|
MYSQL_PASSWORD=""
|
||||||
MYSQL_PASSWORD_SET=0
|
MYSQL_PASSWORD_SET=0
|
||||||
|
EXEC_USER_OVERRIDE=""
|
||||||
|
|
||||||
detect_db_type_from_name() {
|
detect_db_type_from_name() {
|
||||||
name_lower=$(printf '%s' "$1" | tr 'A-Z' 'a-z')
|
name_lower=$(printf '%s' "$1" | tr 'A-Z' 'a-z')
|
||||||
@@ -82,12 +84,19 @@ escape_for_double_quotes() {
|
|||||||
docker_exec() {
|
docker_exec() {
|
||||||
exec_container_name=$1
|
exec_container_name=$1
|
||||||
exec_cmd=$2
|
exec_cmd=$2
|
||||||
|
exec_user=${3:-}
|
||||||
|
|
||||||
curl -fsSL "https://Git.1-H.CC/Scripts/Linux/raw/branch/main/docker-exec-via-sock.sh" | sh -s -- \
|
set -- \
|
||||||
--socket="$DOCKER_SOCKET" \
|
--socket="$DOCKER_SOCKET" \
|
||||||
--api-version="$DOCKER_API_VERSION" \
|
--api-version="$DOCKER_API_VERSION" \
|
||||||
--container="$exec_container_name" \
|
--container="$exec_container_name" \
|
||||||
--cmd="$exec_cmd"
|
--cmd="$exec_cmd"
|
||||||
|
|
||||||
|
if [ -n "$exec_user" ]; then
|
||||||
|
set -- "$@" --user="$exec_user"
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl -fsSL "https://Git.1-H.CC/Scripts/Linux/raw/branch/main/docker-exec-via-sock.sh" | sh -s -- "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
while [ "$#" -gt 0 ]; do
|
while [ "$#" -gt 0 ]; do
|
||||||
@@ -158,6 +167,14 @@ while [ "$#" -gt 0 ]; do
|
|||||||
MYSQL_PASSWORD="$1"
|
MYSQL_PASSWORD="$1"
|
||||||
MYSQL_PASSWORD_SET=1
|
MYSQL_PASSWORD_SET=1
|
||||||
;;
|
;;
|
||||||
|
--exec-user=*)
|
||||||
|
EXEC_USER_OVERRIDE="${1#*=}"
|
||||||
|
;;
|
||||||
|
--exec-user)
|
||||||
|
if [ "$#" -lt 2 ]; then missing_value '--exec-user'; fi
|
||||||
|
shift
|
||||||
|
EXEC_USER_OVERRIDE="$1"
|
||||||
|
;;
|
||||||
--help)
|
--help)
|
||||||
print_usage
|
print_usage
|
||||||
exit 0
|
exit 0
|
||||||
@@ -207,6 +224,8 @@ if [ -z "$DB_TYPE" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
EXEC_USER_DEFAULT=""
|
||||||
|
|
||||||
case $DB_TYPE in
|
case $DB_TYPE in
|
||||||
postgres)
|
postgres)
|
||||||
BACKUP_EXTENSION=".sql.zst"
|
BACKUP_EXTENSION=".sql.zst"
|
||||||
@@ -227,6 +246,7 @@ case $DB_TYPE in
|
|||||||
BACKUP_EXTENSION=".sql.zst"
|
BACKUP_EXTENSION=".sql.zst"
|
||||||
DUMP_CMD="sys_dumpall --clean --username=\"\${DB_USER:-kingbase}\""
|
DUMP_CMD="sys_dumpall --clean --username=\"\${DB_USER:-kingbase}\""
|
||||||
COMPRESS_CMD="zstd"
|
COMPRESS_CMD="zstd"
|
||||||
|
EXEC_USER_DEFAULT="root"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
printf 'Unsupported database type: %s\n' "$DB_TYPE" >&2
|
printf 'Unsupported database type: %s\n' "$DB_TYPE" >&2
|
||||||
@@ -234,6 +254,12 @@ case $DB_TYPE in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if [ -n "$EXEC_USER_OVERRIDE" ]; then
|
||||||
|
EXEC_USER="$EXEC_USER_OVERRIDE"
|
||||||
|
else
|
||||||
|
EXEC_USER="$EXEC_USER_DEFAULT"
|
||||||
|
fi
|
||||||
|
|
||||||
timestamp=$(date +%Y-%m-%d_%H-%M-%S)
|
timestamp=$(date +%Y-%m-%d_%H-%M-%S)
|
||||||
backup_path="$BACKUP_DIR/${BACKUP_PREFIX}${timestamp}${BACKUP_EXTENSION}"
|
backup_path="$BACKUP_DIR/${BACKUP_PREFIX}${timestamp}${BACKUP_EXTENSION}"
|
||||||
|
|
||||||
@@ -244,7 +270,7 @@ cmd="mkdir -p \"${BACKUP_DIR}\" && set -o pipefail && ${DUMP_CMD} | ${COMPRESS_C
|
|||||||
log_border="----------------------------------------------------------------------"
|
log_border="----------------------------------------------------------------------"
|
||||||
|
|
||||||
printf '%s\n' "$log_border" >&2
|
printf '%s\n' "$log_border" >&2
|
||||||
if ! docker_exec "$CONTAINER_NAME" "$cmd"; then
|
if ! docker_exec "$CONTAINER_NAME" "$cmd" "${EXEC_USER:-}"; then
|
||||||
printf '%s\n' "$log_border" >&2
|
printf '%s\n' "$log_border" >&2
|
||||||
log "backup command failed"
|
log "backup command failed"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -257,7 +283,7 @@ log "backup command finished, verifying file size inside container"
|
|||||||
verify_cmd="du -h \"${backup_path}\" 2>/dev/null | awk 'NR==1{print \$1}'"
|
verify_cmd="du -h \"${backup_path}\" 2>/dev/null | awk 'NR==1{print \$1}'"
|
||||||
|
|
||||||
printf '%s\n' "$log_border" >&2
|
printf '%s\n' "$log_border" >&2
|
||||||
size=$(docker_exec "$CONTAINER_NAME" "$verify_cmd" | tr -d '\r')
|
size=$(docker_exec "$CONTAINER_NAME" "$verify_cmd" "${EXEC_USER:-}" | tr -d '\r')
|
||||||
printf '%s\n' "$log_border" >&2
|
printf '%s\n' "$log_border" >&2
|
||||||
|
|
||||||
printf '\n' >&2
|
printf '\n' >&2
|
||||||
|
|||||||
@@ -21,13 +21,14 @@ log_stream() {
|
|||||||
|
|
||||||
print_usage() {
|
print_usage() {
|
||||||
cat <<EOF >&2
|
cat <<EOF >&2
|
||||||
Usage: $0 [--socket=PATH] [--api-version=VERSION] --container=NAME --cmd=COMMAND
|
Usage: $0 [--socket=PATH] [--api-version=VERSION] --container=NAME --cmd=COMMAND [--user=NAME]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--socket=PATH Docker Engine unix socket path (default: /var/run/docker.sock)
|
--socket=PATH Docker Engine unix socket path (default: /var/run/docker.sock)
|
||||||
--api-version=VERSION Docker API version (default: v1.51)
|
--api-version=VERSION Docker API version (default: v1.51)
|
||||||
--container=NAME Container name to execute command in
|
--container=NAME Container name to execute command in
|
||||||
--cmd=COMMAND Command to execute in the container
|
--cmd=COMMAND Command to execute in the container
|
||||||
|
--user=NAME Run command as the specified user (default: container default user)
|
||||||
--shell=SHELL Shell to use (default: sh) 暂未实现
|
--shell=SHELL Shell to use (default: sh) 暂未实现
|
||||||
--help Show this help message
|
--help Show this help message
|
||||||
EOF
|
EOF
|
||||||
@@ -37,6 +38,7 @@ DOCKER_SOCKET="/var/run/docker.sock"
|
|||||||
DOCKER_API_VERSION="v1.51"
|
DOCKER_API_VERSION="v1.51"
|
||||||
CONTAINER_NAME=""
|
CONTAINER_NAME=""
|
||||||
CMD_TO_EXEC=""
|
CMD_TO_EXEC=""
|
||||||
|
EXEC_USER=""
|
||||||
DOCKER_LAST_RESPONSE=""
|
DOCKER_LAST_RESPONSE=""
|
||||||
|
|
||||||
require_command() {
|
require_command() {
|
||||||
@@ -55,13 +57,13 @@ missing_value() {
|
|||||||
docker_exec_create() {
|
docker_exec_create() {
|
||||||
docker_exec_create_desc=$1
|
docker_exec_create_desc=$1
|
||||||
docker_exec_create_cmd=$2
|
docker_exec_create_cmd=$2
|
||||||
docker_exec_create_payload=$(jq -n --arg cmd "$docker_exec_create_cmd" '{
|
docker_exec_create_payload=$(jq -n --arg cmd "$docker_exec_create_cmd" --arg user "$EXEC_USER" '{
|
||||||
AttachStdin: false,
|
AttachStdin: false,
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
Tty: true,
|
Tty: true,
|
||||||
Cmd: ["sh", "-c", $cmd]
|
Cmd: ["sh", "-c", $cmd]
|
||||||
}')
|
} | if ($user | length) > 0 then .User = $user else . end)
|
||||||
|
|
||||||
DOCKER_LAST_RESPONSE=$(curl --silent --show-error --unix-socket "$DOCKER_SOCKET" \
|
DOCKER_LAST_RESPONSE=$(curl --silent --show-error --unix-socket "$DOCKER_SOCKET" \
|
||||||
-X POST \
|
-X POST \
|
||||||
@@ -141,6 +143,14 @@ while [ "$#" -gt 0 ]; do
|
|||||||
shift
|
shift
|
||||||
CMD_TO_EXEC="$1"
|
CMD_TO_EXEC="$1"
|
||||||
;;
|
;;
|
||||||
|
--user=*)
|
||||||
|
EXEC_USER="${1#*=}"
|
||||||
|
;;
|
||||||
|
--user)
|
||||||
|
if [ "$#" -lt 2 ]; then missing_value '--user'; fi
|
||||||
|
shift
|
||||||
|
EXEC_USER="$1"
|
||||||
|
;;
|
||||||
--help)
|
--help)
|
||||||
print_usage
|
print_usage
|
||||||
exit 0
|
exit 0
|
||||||
@@ -180,7 +190,11 @@ fi
|
|||||||
docker_api_base="http://localhost/${DOCKER_API_VERSION}"
|
docker_api_base="http://localhost/${DOCKER_API_VERSION}"
|
||||||
exec_create_endpoint="${docker_api_base}/containers/${CONTAINER_NAME}/exec"
|
exec_create_endpoint="${docker_api_base}/containers/${CONTAINER_NAME}/exec"
|
||||||
|
|
||||||
log "executing command in container '$CONTAINER_NAME': $CMD_TO_EXEC"
|
if [ -n "$EXEC_USER" ]; then
|
||||||
|
log "executing command in container '$CONTAINER_NAME' as '$EXEC_USER': $CMD_TO_EXEC"
|
||||||
|
else
|
||||||
|
log "executing command in container '$CONTAINER_NAME': $CMD_TO_EXEC"
|
||||||
|
fi
|
||||||
|
|
||||||
exec_id=$(docker_exec_create "command" "$CMD_TO_EXEC")
|
exec_id=$(docker_exec_create "command" "$CMD_TO_EXEC")
|
||||||
if [ -z "$exec_id" ]; then
|
if [ -z "$exec_id" ]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user