#!/bin/bash
function show_help() {
echo "用法:"
echo " $0 <SYS_PASSWORD> <TEST_USER> --prepare 准备测试环境并启动写测试"
echo " $0 <SYS_PASSWORD> <TEST_USER> --runtest 运行读测试"
echo " $0 --stop 停止所有测试"
echo " $0 --status 查看测试状态"
echo " $0 --help 显示此帮助信息"
echo ""
echo "参数说明:"
echo " SYS_PASSWORD - 数据库系统用户密码"
echo " TEST_USER - 测试用户名"
echo ""
echo "示例:"
echo " $0 password testuser --prepare"
echo " $0 password testuser --runtest"
echo " $0 --stop"
echo " $0 --status"
exit 0
}
NEEDS_CREDS_COMMANDS=("--prepare" "--runtest")
if [ $# -ge 1 ]; then
FIRST_ARG="$1"
if [[ "$FIRST_ARG" == "--stop" || "$FIRST_ARG" == "--status" || "$FIRST_ARG" == "--help" || "$FIRST_ARG" == "-h" ]]; then
COMMAND="$FIRST_ARG"
case "$COMMAND" in
--help|-h)
show_help
;;
--stop)
function stop_tests() {
LOG_DIR="/tmp/db_test_logs"
WRITE_PID_FILE="$LOG_DIR/write_test.pid"
READ_PID_FILE="$LOG_DIR/read_test.pid"
echo "停止所有测试..."
if [ -f "$WRITE_PID_FILE" ]; then
WRITE_PID=$(cat "$WRITE_PID_FILE")
if ps -p "$WRITE_PID" > /dev/null 2>&1; then
kill -9 "$WRITE_PID" 2>/dev/null
echo "✓ 已停止写测试 (PID: $WRITE_PID)"
else
echo "写测试进程不存在"
fi
rm -f "$WRITE_PID_FILE"
else
echo "写测试未运行"
fi
if [ -f "$READ_PID_FILE" ]; then
READ_PID=$(cat "$READ_PID_FILE")
if ps -p "$READ_PID" > /dev/null 2>&1; then
kill -9 "$READ_PID" 2>/dev/null
echo "✓ 已停止读测试 (PID: $READ_PID)"
else
echo "读测试进程不存在"
fi
rm -f "$READ_PID_FILE"
else
echo "读测试未运行"
fi
echo "清理完成"
}
stop_tests
exit 0
;;
--status)
function show_status() {
LOG_DIR="/tmp/db_test_logs"
WRITE_PID_FILE="$LOG_DIR/write_test.pid"
READ_PID_FILE="$LOG_DIR/read_test.pid"
echo "测试进程状态:"
if [ -f "$WRITE_PID_FILE" ] && ps -p $(cat "$WRITE_PID_FILE") > /dev/null 2>&1; then
WRITE_PID=$(cat "$WRITE_PID_FILE")
echo "✓ 写测试正在运行 (PID: $WRITE_PID)"
echo " 日志文件: $LOG_DIR/write_test.log"
if [ -f "$LOG_DIR/write_test.log" ]; then
echo " 最近日志:"
tail -n 3 "$LOG_DIR/write_test.log"
fi
else
echo "✗ 写测试未运行"
fi
echo ""
if [ -f "$READ_PID_FILE" ] && ps -p $(cat "$READ_PID_FILE") > /dev/null 2>&1; then
READ_PID=$(cat "$READ_PID_FILE")
echo "✓ 读测试正在运行 (PID: $READ_PID)"
echo " 日志文件: $LOG_DIR/read_test.log"
if [ -f "$LOG_DIR/read_test.log" ]; then
echo " 最近日志:"
tail -n 3 "$LOG_DIR/read_test.log"
fi
else
echo "✗ 读测试未运行"
fi
}
show_status
exit 0
;;
esac
fi
fi
if [ $# -lt 3 ]; then
echo "错误: 参数不足"
echo ""
show_help
fi
SYS_PWD=$1
TEST_USER=$2
COMMAND=$3
if [ -z "$SYS_PWD" ]; then
echo "错误: 系统密码不能为空"
exit 1
fi
if [ -z "$TEST_USER" ]; then
echo "错误: 测试用户名不能为空"
exit 1
fi
echo "检查集群状态..."
cms stat -res db | awk 'NR>1 && $3 != "ONLINE" {exit 1}'
if [ $? -eq 0 ]; then
echo "✓ 集群状态正常"
else
echo "✗ 集群有 OFFLINE/UNKNOWN 节点!"
exit 1
fi
CONFIG_FILE="/mnt/dbdata/local/ograc/tmp/data/cfg/ogracd.ini"
if [ ! -f "$CONFIG_FILE" ]; then
echo "错误: 配置文件不存在: $CONFIG_FILE"
exit 1
fi
LOCAL_IPS=$(grep "^LSNR_ADDR" "$CONFIG_FILE" 2>/dev/null | cut -d= -f2 | tr -d ' ' | tr ',' '\n' | grep -v "^127\.")
if [ -z "$LOCAL_IPS" ]; then
echo "错误: 无法从配置文件中获取本地IP"
exit 1
fi
CMS_IPS=$(cms node -list 2>/dev/null | awk 'NR>1 && $3 {print $3}')
if [ -z "$CMS_IPS" ]; then
echo "错误: 无法获取节点列表"
exit 1
fi
CURRENT_IP=""
for ip in $LOCAL_IPS; do
if echo "$CMS_IPS" | grep -q "^$ip$"; then
CURRENT_IP="$ip"
break
fi
done
[ -z "$CURRENT_IP" ] && { echo "错误: 无法确定当前IP"; exit 1; }
PEER_IP=$(echo "$CMS_IPS" | grep -v "^$CURRENT_IP$" | head -n1)
[ -z "$PEER_IP" ] && { echo "错误: 未找到对端IP"; exit 1; }
echo "当前节点IP: $CURRENT_IP"
echo "对端节点IP: $PEER_IP"
LOG_DIR="/tmp/db_test_logs"
mkdir -p "$LOG_DIR"
WRITE_PID_FILE="$LOG_DIR/write_test.pid"
READ_PID_FILE="$LOG_DIR/read_test.pid"
function prepare_test() {
echo "开始准备测试环境..."
echo "创建测试用户 $TEST_USER..."
ogsql SYS/${SYS_PWD}@${CURRENT_IP}:1611 -q -c "DROP USER IF EXISTS ${TEST_USER} CASCADE;" >/dev/null 2>&1
ogsql SYS/${SYS_PWD}@${CURRENT_IP}:1611 -q -c "create user ${TEST_USER} identified by '${SYS_PWD}';" >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "错误: 创建用户失败"
return 1
fi
echo "授权给测试用户..."
ogsql SYS/${SYS_PWD}@${CURRENT_IP}:1611 -q -c "grant create session to ${TEST_USER};grant create table to ${TEST_USER};grant dba to ${TEST_USER};grant inherit privileges on user SYS to ${TEST_USER};" >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "错误: 授权失败"
return 1
fi
echo "创建测试表..."
ogsql ${TEST_USER}/${SYS_PWD}@${CURRENT_IP}:1611 -q -c "CREATE TABLE dual (dummy VARCHAR2(1));INSERT INTO dual (dummy) VALUES ('X');CREATE TABLE test (a_time TIMESTAMP, b_data NUMBER(10));" >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "错误: 创建表失败"
return 1
fi
echo "✓ 测试环境准备完成"
return 0
}
function run_write_test() {
echo "启动写测试 (后台运行)..."
echo "写测试日志: $LOG_DIR/write_test.log"
if [ -f "$WRITE_PID_FILE" ] && ps -p $(cat "$WRITE_PID_FILE") > /dev/null 2>&1; then
echo "写测试已经在运行 (PID: $(cat $WRITE_PID_FILE))"
return 0
fi
(
echo "写测试启动时间: $(date)"
while true; do
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 插入数据..." >> "$LOG_DIR/write_test_debug.log"
ogsql ${TEST_USER}/${SYS_PWD}@${CURRENT_IP}:1611 -q -c "INSERT INTO test (a_time, b_data) SELECT CURRENT_TIMESTAMP, LEVEL FROM dual CONNECT BY LEVEL <= 25;" 2>&1
ogsql ${TEST_USER}/${SYS_PWD}@${PEER_IP}:1611 -q -c "INSERT INTO test (a_time, b_data) SELECT CURRENT_TIMESTAMP, LEVEL FROM dual CONNECT BY LEVEL <= 25;" 2>&1
sleep 0.25
done
) > "$LOG_DIR/write_test.log" 2>&1 &
WRITE_PID=$!
echo $WRITE_PID > "$WRITE_PID_FILE"
echo "✓ 写测试已启动 (PID: $WRITE_PID)"
echo "TEST_USER=$TEST_USER" > "$LOG_DIR/test_info.env"
echo "CURRENT_IP=$CURRENT_IP" >> "$LOG_DIR/test_info.env"
echo "PEER_IP=$PEER_IP" >> "$LOG_DIR/test_info.env"
}
function run_read_test() {
echo "启动读测试..."
echo "读测试日志: $LOG_DIR/read_test.log"
if [ -f "$READ_PID_FILE" ] && ps -p $(cat "$READ_PID_FILE") > /dev/null 2>&1; then
echo "读测试已经在运行 (PID: $(cat $READ_PID_FILE))"
return 0
fi
trap 'echo -e "\n读测试已停止"; exit 0' SIGINT SIGTERM
echo "按 Ctrl+C 停止读测试"
echo "开始时间: $(date)"
echo $$ > "$READ_PID_FILE"
while true; do
stop_time=$(date +%s)
interval=4
start_time=$(($stop_time - $interval))
stop_time_str=$(date "+%Y-%m-%d %H:%M:%S" -d @${stop_time})
start_time_str=$(date "+%Y-%m-%d %H:%M:%S" -d @${start_time})
A=$(ogsql ${TEST_USER}/${SYS_PWD}@${CURRENT_IP}:1611 -q -c "select count(*) from test where a_time >= '${start_time_str}' and a_time <= '${stop_time_str}';" | tail -n 4 | head -n 1 | tr -d ' ')
B=$(ogsql ${TEST_USER}/${SYS_PWD}@${PEER_IP}:1611 -q -c "select count(*) from test where a_time >= '${start_time_str}' and a_time <= '${stop_time_str}';" | tail -n 4 | head -n 1 | tr -d ' ')
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 当前节点: ${A:-0}, 对端节点: ${B:-0}, 时间范围: ${start_time_str} 到 ${stop_time_str}" | tee -a "$LOG_DIR/read_test.log"
if [ "${A:-0}" -eq 0 ] && [ "${B:-0}" -eq 0 ]; then
echo "警告: 两个节点都未读取到数据,写测试可能未运行或有问题" >&2
fi
sleep 1
done
}
function stop_tests() {
echo "停止所有测试..."
if [ -f "$WRITE_PID_FILE" ]; then
WRITE_PID=$(cat "$WRITE_PID_FILE")
if ps -p "$WRITE_PID" > /dev/null 2>&1; then
kill -9 "$WRITE_PID" 2>/dev/null
echo "✓ 已停止写测试 (PID: $WRITE_PID)"
else
echo "写测试进程不存在"
fi
rm -f "$WRITE_PID_FILE"
else
echo "写测试未运行"
fi
if [ -f "$READ_PID_FILE" ]; then
READ_PID=$(cat "$READ_PID_FILE")
if ps -p "$READ_PID" > /dev/null 2>&1; then
kill -9 "$READ_PID" 2>/dev/null
echo "✓ 已停止读测试 (PID: $READ_PID)"
else
echo "读测试进程不存在"
fi
rm -f "$READ_PID_FILE"
else
echo "读测试未运行"
fi
echo "清理完成"
}
case "$COMMAND" in
--prepare)
echo "执行准备测试模式..."
prepare_test
if [ $? -eq 0 ]; then
run_write_test
echo "准备完成,写测试已在后台运行"
echo "使用以下命令查看写测试日志: tail -f $LOG_DIR/write_test.log"
echo "使用以下命令查看测试状态: $0 --status"
echo "使用以下命令运行读测试: $0 $SYS_PWD $TEST_USER --runtest"
else
echo "测试准备失败"
exit 1
fi
;;
--runtest)
echo "执行读测试模式..."
if [ ! -f "$WRITE_PID_FILE" ] || ! ps -p $(cat "$WRITE_PID_FILE") > /dev/null 2>&1; then
echo "警告: 写测试可能未运行,建议先运行: $0 $SYS_PWD $TEST_USER --prepare"
read -p "是否继续? (y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 0
fi
fi
run_read_test
;;
*)
echo "错误: 未知命令 '$COMMAND'"
echo "可用命令: --prepare, --runtest, --stop, --status, --help"
exit 1
;;
esac