在 Shell 脚本中高效连接与操作多种数据库的实战指南

随着 DevOps 与自动化运维的普及,越来越多的场景需要通过 Shell 脚本对数据库进行批量查询、报表导出、定时同步等操作。本文将系统整合 MySQL/MariaDB、PostgreSQL、SQL Server、Oracle 及通用 ODBC 等主流数据库的连接示例与最佳实践,并提供详细注释的完整脚本,帮助你快速上手、避免踩坑。

一、概述

在运维自动化、CI/CD 流水线、定时报表等场景中,Shell 脚本因其轻量、易嵌入 cron 和快速集成而备受青睐。本文将以实战角度,介绍如何在 Shell 中调用各类数据库的命令行客户端(或 ODBC),并通过示例脚本展示:

  • 基本连接与查询
  • 批量事务执行
  • 参数化与错误处理
  • 最佳安全策略
  • 性能优化手段

二、环境准备与前提条件

  1. 命令行客户端

    • MySQL/MariaDB:mysql
    • PostgreSQL:psql
    • SQL Server:sqlcmd
    • Oracle:sqlplus
    • ODBC:isql
  2. Shell 环境

    • 推荐 bash(兼容性好)
    • 已具备基本脚本编辑与执行权限
  3. 网络连通

    • 脚本运行主机需能访问数据库服务器
    • 防火墙、白名单配置完善

三、 MySQL / MariaDB 脚本示例

以下脚本 query_active_users.sh 用于统计 users 表中 status='active' 的用户数。

#!/usr/bin/env bash
#
# 脚本功能:查询 MySQL/MariaDB 数据库中 status='active' 的用户总数
# 用法:bash query_active_users.sh
# 前提:已安装 mysql 客户端;推荐将密码写入 ~/.my.cnf

# === 配置区 ===
DB_HOST="127.0.0.1"          # 数据库主机
DB_PORT="3306"               # 端口号
DB_USER="appuser"            # 用户名
DB_PASS="secret_password"    # 密码(可写入 ~/.my.cnf,避免明文)
DB_NAME="appdb"              # 数据库名

# 构造 SQL 语句
SQL="SELECT COUNT(*) FROM users WHERE status='active';"

# 执行查询:
# -h 主机;-P 端口;-u 用户;-p 密码
# -D 数据库;-N 只输出数据行;-s 安静模式去除额外空格
count=$(mysql -h "${DB_HOST}" \
              -P "${DB_PORT}" \
              -u "${DB_USER}" \
              -p"${DB_PASS}" \
              -D "${DB_NAME}" \
              -N -s \
              -e "${SQL}")

# 输出结果
echo "Active users: ${count}"

3.1.批量事务示例

#!/usr/bin/env bash
#
# 脚本功能:在 MySQL 中执行两步转账操作(事务示例)

# 使用 ~/.my.cnf 管理账号密码,脚本中无需明文
mysql --defaults-file=~/.my.cnf appdb <<EOF
START TRANSACTION;
  UPDATE accounts SET balance = balance - 100 WHERE id = 1001;
  UPDATE accounts SET balance = balance + 100 WHERE id = 2002;
COMMIT;
EOF

四、 PostgreSQL 脚本示例

脚本 query_orders_last24h.sh 用于统计过去 24 小时内新增订单数。

#!/usr/bin/env bash
#
# 脚本功能:查询过去 24 小时内 orders 表中新增订单数
# 用法:bash query_orders_last24h.sh
# 前提:已安装 psql 客户端;推荐使用 ~/.pgpass 管理密码

# === 配置区 ===
export PGPASSWORD="pg_secret"  # PostgreSQL 密码;可写入 ~/.pgpass
DB_HOST="localhost"            # 主机
DB_PORT="5432"                 # 端口
DB_USER="reporter"             # 用户
DB_NAME="salesdb"              # 数据库

# 执行查询:
# -h 主机;-p 端口;-U 用户;-d 数据库
# -t 纯记录输出;-A 无对齐空格
result=$(psql -h "${DB_HOST}" \
              -p "${DB_PORT}" \
              -U "${DB_USER}" \
              -d "${DB_NAME}" \
              -t -A \
              -c "SELECT COUNT(*) FROM orders WHERE created_at > now() - interval '1 day';")

echo "24h 新增订单: ${result}"

4.1.参数化与事务

#!/usr/bin/env bash
#
# 脚本功能:更新用户最后登录时间,并写入登录日志(参数化事务)

USER_ID="${1:-0}"  # 从脚本参数读取 user_id;默认 0

SQL=$(cat <<EOF
BEGIN;
  UPDATE users SET last_login = now() WHERE id = \$1;
  INSERT INTO login_log(user_id, login_time) VALUES(\$1, now());
COMMIT;
EOF
)

psql -v ON_ERROR_STOP=1 \
     -h host -U user -d dbname \
     --set=1="${USER_ID}" \
     -c "${SQL}"

五、 SQL Server 脚本示例

脚本 sqlserver_count.sh 用于统计 customers 表总行数。

#!/usr/bin/env bash
#
# 脚本功能:查询 SQL Server customers 表总行数
# 用法:bash sqlserver_count.sh
# 前提:安装 sqlcmd 客户端

# === 配置区 ===
DB_SERVER="192.168.1.100"       # 服务器地址
DB_PORT="1433"                  # 端口
DB_USER="sa"                    # 用户
DB_PASS="Strong!Pass1"          # 密码
DB_NAME="CRM"                   # 数据库

# 执行查询:
# -S 服务器,端口;-U 用户;-P 密码
# -d 数据库;-h -1 去列头;-W 去尾空格
count=$(sqlcmd -S "${DB_SERVER},${DB_PORT}" \
               -U "${DB_USER}" \
               -P "${DB_PASS}" \
               -d "${DB_NAME}" \
               -h -1 -W \
               -Q "SET NOCOUNT ON; SELECT COUNT(*) FROM customers;")

echo "Total customers: ${count}"

六、 Oracle 脚本示例

脚本 oracle_query.sh 用于统计 employees 表中 status='ACTIVE' 的员工数。

#!/usr/bin/env bash
#
# 脚本功能:查询 Oracle employees 表中 ACTIVE 员工数
# 用法:bash oracle_query.sh
# 前提:安装 sqlplus 客户端

# === 配置区 ===
DB_CONN="appuser/securepwd@//127.0.0.1:1521/ORCLPDB1"  # user/pass@//host:port/SERVICE

# 使用 here-doc 传递多行命令给 sqlplus
active_count=$(sqlplus -s "${DB_CONN}" <<EOF
SET HEADING OFF    -- 不显示列名
SET FEEDBACK OFF   -- 不显示行数反馈
SELECT COUNT(*) FROM employees WHERE status='ACTIVE';
EXIT;
EOF
)

# 去除首尾空格
active_count=$(echo "${active_count}" | xargs)

echo "Active employees: ${active_count}"

七、 通用 ODBC 脚本示例

如需对任意已配置 DSN 的数据库执行 SQL,可使用 isql

#!/usr/bin/env bash
#
# 脚本功能:通过 ODBC DSN 执行自定义 SQL
# 用法:bash odbc_query.sh
# 前提:/etc/odbc.ini 已配置 DSN

DSN="MyDSN"         # 数据源名称
USER="odbcuser"     # 用户
PASS="odbcpass"     # 密码

# 将 SQL 通过管道传给 isql
echo "SELECT name, email FROM users WHERE active=1;" | \
  isql -v "${DSN}" "${USER}" "${PASS}"

八、安全性与密码管理

  • 配置文件管理
    • MySQL:~/.my.cnf(权限 600
    • PostgreSQL:~/.pgpass(权限 600
  • 环境变量注入
    • export MYSQL_PWD=…export PGPASSWORD=…
  • 最小权限原则
    • 脚本所用账号仅授予必要读写权限
  • 加密传输
    • 使用 SSL/TLS 连接数据库,防止中间人攻击

九、错误处理与日志记录

#!/usr/bin/env bash
set -o errexit    # 遇错即退出
set -o nounset    # 未定义变量报错
set -o pipefail   # 管道任一失败即报错

LOGFILE="/var/log/db_script.log"
# 将 stdout/stderr 重定向到日志
exec 1>>"${LOGFILE}" 2>&1

echo "[$(date '+%F %T')] 脚本开始"
# … 执行数据库操作 …
echo "[$(date '+%F %T')] 脚本结束"
  • errexitnounsetpipefail 提升健壮性
  • 日志中记录执行时间与关键信息,便于排查

十、性能优化与并发控制

  • 批量提交:避免在循环中频繁启动客户端
  • 连接池 / 代理:使用 PgBouncer、MySQL Proxy 重用连接
  • 并行执行:借助 xargs -P 或 GNU parallel
# 并行执行 5 个查询任务
printf "%s\n" user1 user2 user3 user4 user5 | \
  xargs -n1 -P5 -I{} bash query_user.sh "{}"

十一、结语

本文整合了在 Shell 脚本中访问 MySQL/MariaDB、PostgreSQL、SQL Server、Oracle 与通用 ODBC 的全方位示例,并提供了安全、错误处理与性能优化的最佳实践。通过这些脚本,你可以轻松构建自动化报表、定时同步、运维监控等系统。希望本文能成为你在数据库自动化道路上的有力参考,助你快速实现高效、可靠的运维脚本!

你可能感兴趣的:(运维,其他,数据库,运维)