前天正在跟前端的同事调试功能。服务器开好,模拟的玩家登录好,就在倒计时。这时突然运营的同事跑过来说要统计几个服务器玩家的一些情况,也就是需要从几个服的数据库导出部分玩家的数据。好吧,我看了一下时间,11:47。心想,跟前端调试完,去吃个饭再午休一下那就下午再给吧。没想对方来一句"就导个数据库而已,要这么久么?",而且还是直接跟我上司说的。我嚓,好吧,我导。可问题来了,平时的统计是由php做的,批量部署这些是由运维做的。服务端完全没有对应的工具。而且服务器是在阿里云上的,数据库的用户是限制了ip段登录的,我所在的ip没法登录的。于是,只好终止调试,切ip,写sql,然后用navicat手动一个个服务器导出数据到excel。

  事后想想,还是写个脚本吧,不然以后还是会被坑的。

  从环境来看,数据库不能直接登录,没法直接导出。不过可以由运维提供key通过ssh登录到远程服务器再将数据导出到本地。

  先配置ssh通过key登录服务器。这里略过...

  然后就是通过ssh执行命令。先看一下ssh的帮助文档:

usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
[-D [bind_address:]port] [-E log_file] [-e escape_char]
[-F configfile] [-I pkcs11] [-i identity_file]
[-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]
[-O ctl_cmd] [-o option] [-p port]
[-Q cipher | cipher-auth | mac | kex | key]
[-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]
[-w local_tun[:remote_tun]] [user@]hostname [command]

最后一项就是执行指令的。假如远程服务器地址为180.97.33.108,开启的ssh端口为998,ssh用户名为xzc,然后想通过在远程服务器上执行命令ls,那么脚本应该这么写:

ssh xzc@180.97.33.108 -p  "ls"

如果ssh的认证key已配置好,那么会把登录后当前目录下的文件列出来,当然第一次登录会提示保存远程服务器的指纹。现在是要导出数据库的数据,那么需要把ls命令换成导出数据库的命令。

echo "select * from user;" | mysql xzc_db -uxzc -pxzcpwd
#或者
mysql xzc_db -uxzc -pxzcpwd -e "select * from user"

上面两命令都可以使用数据库用户xzc,密码xzcpwd从数据库xzc_db打印出user表,使用的是默认的本地数据库地址localhost,默认的端口。如果不是默认,需要指定。

   登录OK了,打印也OK了,那么下一步就是导出到文件了。这在bash也就是一个 > 的事。把上面的命令拼起来就是:

ssh xzc@180.97.33.108 -p  'echo "select * from user;" | mysql xzc_db -uxzc -pxzcpwd' > user.txt

这样就把user表导出来本地的user.txt中了。注意"> user.txt"如果放到 ''里则是在远程服务器执行,导出的文件在远程服务器。文件现在也有了,不过是txt,这样交给运营不太好吧。那就导出excel吧。不过遗憾的是我查了N多资料,也找不到mysql不依赖第三方插件或工具导出原生excel的方法。而navicat导出的可是货真价实的excel,如果用notepad++之类的文本工具打开是会乱码的,并且导出的文件不会有编码问题。幸好如果一个txt以tab分割的话,excel也是能认得出来的。于是把user.txt改名user.xls就可以了。但这样做的问题是excel会按自己的方式处理内容的。比如把一个很大的数字转换成科学记数法形式。这些都得手动去处理一下了。

  最后,就是写成脚本批量操作了。附上我使用的脚本一个:

#!/bin/bash

# 通过ssh远程执行远程指令
# 需要先部署key认证,保证ssh只需要ip、port即可连接
# 如果需要和远程服务器交互,请参考ssh的-t、-tt参数
# 如果需要反复登录服务器执行多条指令,请使用ssh的通道重用
# 参考:http://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing
# 使用通道需要注意退出通道,如"ssh github.com -O exit"或者"ssh github.com -O stop"
# --by coding my life #分别设置ssh用户名、数据库用户名、数据库密码、导出数据
SSH_USER='xzc_ssh'
DB_USER='xzc_db'
DB_PWD='xzc_db_pwd123'
EXP_PATH=export_data/ # 执行远程命令
# $ 服务器ip
# $ ssh端口
# $ 指令
function exec_remote_command()
{
ssh $SSH_USER@$ -p $ '$3'
} # 执行远程sql,导出数据
# $ 服务器ip
# $ ssh端口
# $ 指令,多个sql指令如select * from user;select * from bag;也可执行,但结果将会写到同一个文件
# s4 服务器
# $ 导出文件
function export_remote_sql()
{
echo export from $ ...
cmd="echo \"$3\" | mysql $4 -u$DB_USER -p$DB_PWD --default-character-set=utf8" ssh $SSH_USER@$ -p $ "$cmd" > $EXP_PATH$4_$ #如果要导出到远程服务器,将把 > $EXP_PATH$4_$5放到cmd中
} # $ 区服名
# $ ip
# $ 端口
function exec_sqls()
{
cat SQLS | while read sql ; do fc=${sql::}
if [ "#" == "$fc" ]; then #被注释的不处理
continue
fi #sql语句中包含空格,不能再以空格来区分。最后一个空格后的是导出的文件名
exp_file="${sql##* }" #两个#表示正则以最大长度匹配*和一个空格(*后面的空格),截取余下的赋值给exp_file
sql_cmd="${sql%% $exp_file}" #两个%表示从右至左删除%%以后的内容 export_remote_sql $ $ "$sql_cmd" $ "$exp_file"
done
} # 需要在当前目录下创建服务器列表文件SERVERS,格式为"数据库名 ip ssh端口",如"xzc_game_s99 127.0.0.1 22"
# 需要在当前目录下创建sql命令列表文件SQLS,格式为"sql语句 导出的文件",如"select * from user; user.xls"
# 多个sql请注意用;分开,sql必须以;结束
# 文件名中不能包含空格,最终导出的文件为"数据库名_文件名",如"xzc_game_s99_user.xls" mkdir -p $EXP_PATH cat SERVERS | while read server ; do fc=${server::}
if [ "#" == "$fc" ]; then #被注释的不处理
continue
fi name=`echo $server|awk '{print $1}'`
ip=`echo $server|awk '{print $2}'`
port=`echo $server|awk '{print $3}'` exec_sqls $name $ip $port
done

当前目录下的文件如下,其中SERVERS是服务器列表,里面指定数据库名,ip,ss端口,SQLS则指定sql指令及导出的文件名。这两个文件里以#开头的都不会处理:

xzc@xzc-HP-ProBook-4446s:~/桌面/remote_cmd$ ls
remote_cmd.sh SERVERS SQLS
xzc@xzc-HP-ProBook-4446s:~/桌面/remote_cmd$ cat SERVERS
xzc_game_s99 120.0.0.99
xzc_game_s91 120.0.0.91
xzc_game_s92 120.0.0.92
xzc_game_s93 120.0.0.93
xzc_game_s94 120.0.0.94
#xzc_game_s91 120.0.0.91 xzc@xzc-HP-ProBook-4446s:~/桌面/remote_cmd$ cat SQLS
#select * money from money; money.xls
select * from user; user.xls
xzc@xzc-HP-ProBook-4446s:~/桌面/remote_cmd$

  到这里,脚本基本完成了要求。

使用ssh远程执行命令批量导出数据库到本地的更多相关文章

  1. 使用ssh远程执行命令批量导出数据库到本地(转)

    前天正在跟前端的同事调试功能.服务器开好,模拟的玩家登录好,就在倒计时.这时突然运营的同事跑过来说要统计几个服务器玩家的一些情况,也就是需要从几个服的数据库导出部分玩家的数据.好吧,我看了一下时间,1 ...

  2. 利用scp 远程上传下载文件/文件夹和ssh远程执行命令

    利用scp传输文件 1.从服务器下载文件scp username@servername:/path/filename /tmp/local_destination例如scp codinglog@192 ...

  3. 解决SSH远程执行命令找不到环境变量的问题

    通过SSH执行远程主机的命令或脚本时,经常会出现找不到自定义环境变量的问题.但是,如果通过SSH登录远程主机,然后再执行相同的命令或脚本,那么此时执行又是成功的.两种相似的方法,得到的结果却截然不同, ...

  4. 网络编程 - 1.简单的套接字通信/2.加上通信循环/3.bug修复/4.加上链接循环/5.模拟ssh远程执行命令

    1.简单的套接字通信 服务端 ''' 服务端 接电话 客户端 打电话 1.先启动服务端 2.服务端有两种套接字 1.phone 用来干接收链接的 2.conn 用来干收发消息的 ''' import ...

  5. ssh远程执行命令使用明文密码

    经过不懈的搜索终于找到ssh远程执行命令使用明文密码使用sshpass. 例子: sshpass -p "sequoiadb" ssh root@localhost "l ...

  6. SSH远程执行命令环境变量问题

    SSH命令格式 usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address: ...

  7. 模拟ssh远程执行命令,粘包问题,基于socketserver实现并发的socket

    06.27自我总结 1.模拟ssh远程执行命令 利用套接字编来进行远程执行命令 服务端 from socket import * import subprocess server = socket(A ...

  8. 网络编程之模拟ssh远程执行命令、粘包问题 、解决粘包问题

    目录 模拟ssh远程执行命令 服务端 客户端 粘包问题 什么是粘包 TCP发送数据的四种情况 粘包的两种情况 解决粘包问题 struct模块 解决粘包问题 服务端 客户端 模拟ssh远程执行命令 服务 ...

  9. [转帖]ssh 远程执行命令

    ssh 远程执行命令 https://www.cnblogs.com/youngerger/p/9104144.html SSH 是 Linux 下进行远程连接的基本工具,但是如果仅仅用它来登录那可是 ...

随机推荐

  1. poj 2441 Arrange the Bulls(状态压缩dp)

    Description Farmer Johnson's Bulls love playing basketball very much. But none of them would like to ...

  2. class 类(1)

    创建类 #!/usr/bin/env python # coding=utf-8 __metaclass__ = type class Person: def __init__(self, name) ...

  3. 关于背景透明,文字不透明的最佳方法,兼容IE

    以背景黑色,透明度0.5举例 非IE:background:rgba(0,0,0,0.5); IE:filter:progid:DXImageTransform.Microsoft.gradient( ...

  4. Android动态加载jar/dex

    前言 在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优 ...

  5. Android Xfermode 实战 实现圆形、圆角图片

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42094215,本文出自:[张鸿洋的博客] 1.概述 其实这篇本来准备Androi ...

  6. JavaScript 公有 私有 静态属性和方法

    1.公有属性和公有方法 这里的 name  age  都是参数传递进去 可以在外面直接实例化调用. 2.私有属性和方法 私有的只能在函数内部使用 作用域的原因 3.静态属性和静态方法 这里我首先 创建 ...

  7. compass安装

    修改ruby软件包的sources 国外服务器不给力,经常链接失败,换成国内淘宝的:https://ruby.taobao.org/ 先移除本有的sources gem sources --remov ...

  8. OWIN启动项的检测

    OWIN启动项的检测 通过以下方法设置启动项: 命名约定 Katana在命名空间内查找StartUp类 OwinStartup Attribute [assembly: OwinStartup(typ ...

  9. android 5.0 受欢迎的API简介

    android 5.0 作为系统的一次重大升级,给用户和开发者带来了全新的体验.Material Design不但在视觉和操作上更胜一筹,扩展UI工具包同时也引入了大量新的API. 1. 3D视图和实 ...

  10. [OC笔记] static 关键字

    在变量声明前加上static关键字,可以使局部变量保留多次方法调用所得到的值.当多个方法对一个静态变量进行操作时,多个方法共享同一个静态变量的值.