You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
zeus/docker/tidb/tools/container_debug

191 lines
5.4 KiB
Bash

#!/bin/bash
# Copyright 2018 PingCAP, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
#* --------------------------------------------------------------------- */
#* log configure */
#* --------------------------------------------------------------------- */
### Define logging color
COLOR_ORIGIN="\033[0m"
COLOR_GREEN="\033[32m"
COLOR_YELLOW="\033[33m"
COLOR_RED="\033[31m"
### Define logging level
LOGGER_LEVEL="3"
### Define common logger
function logger() {
cur_level=$1
cur_type=$2
cur_color=$3
shift && shift && shift
cur_msg=$*
[[ ${LOGGER_LEVEL} -lt ${cur_level} ]] && return 0
pre_fix="${cur_color}[${cur_type}][$(date +%F)][$(date +%T)]"
pos_fix="${COLOR_ORIGIN}"
echo -e "${pre_fix} ${cur_msg} ${pos_fix}"
}
### Define notice logger
function notice() {
logger 3 "NOTICE" ${COLOR_GREEN} $*
}
### Define warning logger
function warning() {
logger 2 "WARNING" ${COLOR_YELLOW} $*
}
### Define fatal logger
function fatal() {
logger 1 "FATAL" ${COLOR_RED} $*
exit 1
}
##########################################################################
function print_help() {
echo "\
${1:-Debug tool for container.}
Usage:
container_debug [OPTIONS] [ARG]
Options:
-i The container's identity, possible values are 'containerID' or 'containerName'
-s The service name defined in docker-compose
-w Run pprof via a web interface for go program
-p The binary path of the debugged process in its own container
-h Print help infomation
When you enter the debug container, you can find the pid of the debugged process through the ps command,
then you can find the binary of the debugged process through this path /proc/\${pid}/root/\${binary_path}.
\${binary_path} represents the binary path of the debugged process in its own container.
\${pid} represents the process id of the debugged process as seen in the debug container.
" >&2
exit
}
###############################variable define##################################
WORKSPACE=$(cd $(dirname $0)/..; pwd)
DEBUG_IMAGE=${DEBUG_IMAGE:-uhub.service.ucloud.cn/pingcap/tidb-debug:latest}
SUFFIX=$(uuidgen|cut -d'-' -f1|tr '[A-Z]' '[a-z]')
DEBUG_CONTAINER_NAME=debug-${SUFFIX}
TMP_FILE=$(mktemp /tmp/binary.XXXXXX)
################################################################################
if [[ $# -eq 0 ]]
then
print_help
fi
function cleanup() {
notice "start to clean tmp file ${TMP_FILE}"
[[ -f ${TMP_FILE} ]] && rm -f ${TMP_FILE}
}
### register signal processing function
trap cleanup EXIT
### change workspace
cd $WORKSPACE
optstring=":i:s:p:wh"
while getopts "$optstring" opt; do
case $opt in
i)
container_id=${OPTARG}
;;
s)
service_name=${OPTARG}
;;
p)
binary_path=${OPTARG}
;;
w)
web=true
;;
h)
print_help
;;
\?)
fatal "Invalid option: -$OPTARG" >&2
;;
:)
fatal "Option -$OPTARG requires an argument" >&2
;;
esac
done
if [[ -z ${service_name} && -z ${container_id} ]]
then
fatal "please use -s or -i options to select the target container" >&2
elif [[ ! -z ${container_id} ]]
then
### If both -s and -i options are specified, the -i option is preferred
cid=${container_id}
else
cprefix=$(basename $(pwd)|tr -Cd '[A-Za-z0-9]'|tr '[A-Z]' '[a-z]')
cid="${cprefix}_${service_name}_1"
docker ps | grep ${cid} >/dev/null
[[ $? -ne 0 ]] && fatal "not found docker-compose service ${service_name}, please confirm the correct docker-compose service name" >&2
fi
if [[ ! -z ${binary_path} ]]
then
binary_name=$(basename ${binary_path})
docker cp ${cid}:${binary_path} ${TMP_FILE}
if [[ $? -ne 0 ]]
then
### not found binary in container, reset variable ${binary_name}
binary_name=
warning "not found ${binary_path} in container ${cid}, please specify the correct binary path in container" >&2
fi
fi
if [[ ! -z ${web} ]]
then
### starts a web server for graphic visualizations of golang program profiles
### generate a random web port
### TODO: Test whether this port has been used
wport=${RANDOM}
[[ ${wport} -lt 10000 ]] && wport=$((wport+10000))
### get the container exposed port
cport=$(docker port ${cid}|grep -E '[0-9]{5}'|awk -F: '{print $NF}')
notice "starts a web server on localhost:${wport}"
pprof -http=:${wport} ${TMP_FILE} http://localhost:${cport}/debug/pprof/profile
else
### enter debug container to debug the specified container
docker_run_args=(-ti --rm --name=${DEBUG_CONTAINER_NAME})
docker_run_args+=(--pid=container:${cid})
docker_run_args+=(--network=container:${cid})
docker_run_args+=(--ipc=container:${cid})
docker_run_args+=(--cap-add=SYS_PTRACE)
docker_run_args+=(--privileged=true)
if [[ ! -z ${binary_name} && -e ${TMP_FILE} ]]
then
docker_run_args+=(-v ${TMP_FILE}:/${binary_name})
else
notice "you can access the debugged container ${cid} file system through this path /proc/\${DEBUGGED_PROCESS_PID}/root"
fi
docker_run_args+=($DEBUG_IMAGE)
docker run ${docker_run_args[@]}
fi