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.
191 lines
5.4 KiB
Bash
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
|