import
subprocess
import
shutil
import
os
import
sys
reload
(sys)
sys.setdefaultencoding(
'utf-8'
)
import
optparse
import
ConfigParser
import
time
import
jinja2
import
urllib2
import
json
import
socket
try
:
import
fcntl
except
:
pass
import
struct
import
MySQLdb
def
get_ip_address(ifname):
s
=
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return
socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915
,
struct.pack(
'256s'
, ifname[:
15
])
)[
20
:
24
])
class
Cqby:
def
__init__(
self
, version, platform, platformid,
id
):
self
.version
=
version
self
.platform
=
platform
self
.platformid
=
platformid
self
.
id
=
id
self
.workdir
=
'/data/init'
self
.gamedir
=
'/data/game/game%s'
%
self
.
id
try
:
os.makedirs(
'/data/game'
)
except
:
print
"目录已存在"
self
.chatdir
=
'/data/game/chat%s'
%
self
.
id
if
int
(
self
.
id
) >
50000
:
self
.gameport
=
str
(
self
.
id
)
else
:
self
.gameport
=
20000
+
int
(
self
.
id
)
self
.gameport
=
str
(
self
.gameport)
try
:
self
.localip
=
get_ip_address(
'eth0'
)
except
:
self
.localip
=
get_ip_address(
'em1'
)
self
.dbname
=
'game%s'
%
self
.
id
self
.admindbuser
=
'root'
self
.admindbpass
=
'123456'
self
.backup
=
'/data/backup'
try
:
os.makedirs(
self
.backup)
except
:
print
"目录已经存在"
self
.gamelogdir
=
'/data/gamelogs/chuanqi/%s/S%s'
%
(
self
.platform,
self
.
id
)
if
not
os.path.isdir(
self
.gamelogdir):
os.makedirs(
self
.gamelogdir)
subprocess.call(
'chown www:www -R /data/gamelogs'
,shell
=
True
)
self
.binConfigDir
=
'%s/bin'
%
self
.gamedir
self
.binConfigFiles
=
[
'socket.jinja2'
]
self
.confConfigDir
=
'%s/conf'
%
self
.gamedir
self
.confConfigFiles
=
[
'jade.cfg.jinja2'
]
self
.independentConfigDir
=
'%s/conf/independent'
%
self
.gamedir
self
.independentConfigFiles
=
[
'auth.properties.jinja2'
,
'debug.properties.jinja2'
,
'fcm.properties.jinja2'
,
'gm.properties.jinja2'
,
'net.properties.jinja2'
,
'server.properties.jinja2'
,
'whiteList.properties.jinja2'
,
'onlineLimit.properties.jinja2'
,
]
self
.miscConfigDir
=
'%s/conf/config/common'
%
self
.gamedir
self
.miscConfigFiles
=
[
'misc.properties.jinja2'
,
]
baselist
=
[
'127.0.0.1'
,]
payIPListAll
=
{
'37wan'
: [],
'liebao'
: [],
'2345'
: [],
'yilewan'
: [],
'renrenwang'
: [],
'6711'
: [],
'1360'
: [],
'duowan'
: [],
'baidu'
: [],
'lianyun'
: [],
'tencent'
: []
}
try
:
self
.platformPayList
=
payIPListAll[
self
.platform]
except
:
self
.platformPayList
=
payIPListAll[
'lianyun'
]
self
.payList
=
baselist
+
self
.platformPayList
self
.mergelist
=
self
.__getMerge()
def
__getMerge(
self
):
i
=
0
while
True
:
try
:
if
i >
=
3
:
print
"请求超时!!!!!!"
sys.exit(
2
)
url
=
'http://yw.admin.xxx.com/yunwei/api/getmergetarget/%s/%s/'
%
(
self
.platform,
self
.
id
)
request
=
urllib2.urlopen(url)
response
=
request.read().split(
','
)
except
Exception, e:
print
"请求合服信息失败:"
+
str
(e)
print
"正在重试。。。"
i
=
i
+
1
else
:
break
return
response
def
createDatabase(
self
):
try
:
print
"正在创建数据库:%s"
%
self
.dbname
cmd
=
%
(
self
.admindbuser,
self
.admindbpass,
self
.dbname)
ret
=
subprocess.call(cmd,shell
=
True
)
print
"执行状态:%s"
%
ret
if
ret:
print
"创建数据库失败,请确认!"
sys.exit(
2
)
except
Exception,e:
print
"捕捉到异常:"
,e
sys.exit(
2
)
def
updateDB(
self
, filename):
try
:
print
"正在导入SQL文件:%s"
%
filename
cmd
=
%
(
self
.admindbuser,
self
.admindbpass,
self
.dbname, filename)
ret
=
subprocess.call(cmd, shell
=
True
)
print
"执行状态:%s"
%
ret
except
Exception,e:
print
"捕捉到异常:"
,e
sys.exit(
2
)
def
dumpDatabase(
self
):
try
:
print
"正在备份数据库:%s"
%
self
.dbname
curTime
=
time.strftime(
'%Y%m%d%H%M%S'
, time.localtime(time.time()))
cmd
=
%
(
self
.admindbuser,
self
.admindbpass,
self
.dbname, '
%
s
/
%
s
-
%
s.sql'
%
(
self
.backup,curTime,
self
.dbname))
ret
=
subprocess.call(cmd, shell
=
True
)
print
"执行状态:%s"
%
ret
except
Exception,e:
print
"捕捉到异常:"
,e
def
dropDatabase(
self
):
try
:
print
"正在删除数据库:%s"
%
self
.dbname
cmd
=
%
(
self
.admindbuser,
self
.admindbpass,
self
.dbname)
ret
=
subprocess.call(cmd, shell
=
True
)
print
"执行状态:%s"
%
ret
except
Exception,e:
print
"捕捉到异常:"
,e
def
createGameDir(
self
):
try
:
print
"正在检测目录是否存在:%s"
%
self
.gamedir
if
os.path.isdir(
self
.gamedir):
print
"目录已存在,请检查参数!"
sys.exit(
2
)
else
:
print
"正在复制程序文件至:%s"
%
self
.gamedir
shutil.copytree(
'%s/%s/server'
%
(
self
.workdir,
self
.version),
self
.gamedir)
except
Exception,e:
print
"捕捉到异常:"
,e
sys.exit(
2
)
def
dropGameDir(
self
):
try
:
print
"正在删除游戏目录:%s"
%
self
.gamedir
if
os.path.isdir(
self
.gamedir):
shutil.rmtree(
self
.gamedir)
except
Exception,e:
print
"遇到错误:"
,e
def
dropGameLogDir(
self
):
try
:
print
"正在删除日志目录:%s"
%
self
.gamelogdir
if
os.path.isdir(
self
.gamelogdir):
shutil.rmtree(
self
.gamelogdir)
except
Exception,e:
print
"遇到错误:"
,e
def
createConfig(
self
, configdir, configlist):
try
:
print
"正在生成配置文件:%s"
%
configdir
url
=
'http://yw.admin.xxx.com/yunwei/api/getmem/%s/%s'
%
(
self
.platform,
self
.
id
)
response
=
urllib2.urlopen(url)
mem
=
response.read()
env
=
jinja2.Environment(loader
=
jinja2.FileSystemLoader(configdir))
for
gateconfig
in
configlist:
print
gateconfig
template
=
env.get_template(gateconfig)
f
=
open
(
'%s/%s'
%
(configdir,gateconfig.rstrip(
'.jinja2'
)),
'w'
)
f.write(
template.render(
version
=
self
.version,
platformid
=
self
.platformid,
platform
=
self
.platform,
gameid
=
self
.
id
,
gameport
=
self
.gameport,
gamedir
=
self
.gamedir,
dbuser
=
'game'
,
dbpass
=
'game123456'
,
dbname
=
self
.dbname,
paylist
=
self
.platformPayList,
mem
=
mem,
mergelist
=
self
.mergelist,
)
)
f.close()
except
Exception,e:
print
"生成配置文件遇到错误:"
,e
sys.exit(
2
)
def
updateconfig(
self
):
self
.createConfig(
self
.binConfigDir,
self
.binConfigFiles)
os.chmod(
'%s/bin/socket'
%
self
.gamedir,
0755
)
self
.createConfig(
self
.confConfigDir,
self
.confConfigFiles)
self
.createConfig(
self
.independentConfigDir,
self
.independentConfigFiles)
def
updategame(
self
):
print
"正在更新游戏程序。。。"
cmd
=
%
(
self
.workdir,
self
.version,
self
.gamedir)
print
cmd
result
=
subprocess.call(cmd, shell
=
True
)
return
result
def
start(
self
):
print
"给JSVC添加执行权限:"
os.chmod(
'%s/bin/jsvc'
%
self
.gamedir,
0755
)
print
"正在启动服务:"
cmd
=
%
self
.gamedir
result
=
subprocess.call(cmd, shell
=
True
)
return
result
def
stop(
self
):
print
"正在关闭服务:"
cmd
=
%
self
.gamedir
result
=
subprocess.call(cmd, shell
=
True
)
return
result
def
clearnow(
self
):
self
.dumpDatabase()
self
.updateDB(
'%s/%s/server/sql/database.sql'
%
(
self
.workdir,
self
.version))
self
.dropGameLogDir()
def
clear(
self
):
try
:
conn
=
MySQLdb.connect(user
=
self
.admindbuser, passwd
=
self
.admindbpass, host
=
'localhost'
, db
=
self
.dbname, unix_socket
=
'/tmp/mysql.sock'
)
cursor
=
conn.cursor(cursorclass
=
MySQLdb.cursors.DictCursor)
sql
=
sum
=
cursor.execute(sql)
cursor.close()
conn.close()
print
"数据库Player表有:%s"
%
sum
if
int
(
sum
) >
30
:
print
"Player表记录总数大于30!请确认后再执行清档操作!!!"
sys.exit(
2
)
else
:
print
"Player表记录总数小于30,可以执行清档操作!"
self
.stop()
self
.clearnow()
self
.start()
except
Exception,e:
print
"连接数据库错误:%s"
%
e
sys.exit(
2
)
def
create(
self
):
self
.createDatabase()
self
.updateDB(
'%s/%s/server/sql/database.sql'
%
(
self
.workdir,
self
.version))
self
.mysqlgrant()
self
.createGameDir()
self
.updateconfig()
self
.createchat()
self
.nginxlogs()
def
drop(
self
):
self
.dumpDatabase()
self
.dropDatabase()
self
.dropGameDir()
self
.dropGameLogDir()
self
.dropchat()
def
onekey(
self
):
self
.stop()
time.sleep(
10
)
self
.updategame()
self
.start()
def
mysqlgrant(
self
):
print
"正在添加数据库授权:"
for
ip
in
self
.payList:
print
"正在添加%s权限"
%
ip
cmd
=
%
(
self
.admindbuser,
self
.admindbpass, ip)
subprocess.call(cmd, shell
=
True
)
cmd
=
%
(
self
.admindbuser,
self
.admindbpass)
subprocess.call(cmd, shell
=
True
)
if
__name__
=
=
"__main__"
:
active_list
=
[
'create'
,
'drop'
,
'updateconfig'
,
'start'
,
'stop'
,
'clear'
,
'updategame'
,
'updateDB'
,
'onekey'
,
'mysqlgrant'
,
'clearnow'
]
gamever_list
=
[
'test'
,
'37dev'
,
'37stable'
]
usage
=
parser
=
optparse.OptionParser(
usage
=
usage,
version
=
"%prog 2.0"
)
setplat_opts
=
optparse.OptionGroup(
parser,
'设置服务器平台标识'
,
'一台硬件服务器设置一次即可。'
)
setplat_opts.add_option(
'-p'
,
'--platform'
,
dest
=
"platform"
,
help
=
"平台名称"
)
parser.add_option_group(setplat_opts)
tools_opts
=
optparse.OptionGroup(
parser,
'服务器日常功能'
,
)
tools_opts.add_option(
'-v'
,
'--ver'
,
dest
=
"ver"
,
help
=
"版本目录"
,
type
=
"choice"
,
choices
=
gamever_list,
default
=
gamever_list[
1
]
)
tools_opts.add_option(
'-i'
,
'--id'
,
dest
=
'id'
,
help
=
"服务器ID"
)
tools_opts.add_option(
'-a'
,
'--action'
,
dest
=
'action'
,
help
=
"执行动作"
,
type
=
"choice"
,
choices
=
active_list
)
tools_opts.add_option(
'-s'
,
'--sql'
,
dest
=
'sql'
,
help
=
"SQL文件(可选,配合updateDB使用)"
)
parser.add_option_group(tools_opts)
options, args
=
parser.parse_args()
err_msg
=
'参数不对,请输--help查看详细说明!'
ini
=
'platform.ini'
if
options.platform:
apiurl
=
'http://yw.admin.xxx.com/yunwei/api/getplatforminfo/'
ini
=
'platform.ini'
result
=
urllib2.urlopen(apiurl)
response
=
json.loads(result.read())
for
code,
id
in
response.items():
if
options.platform
=
=
code:
platformid
=
id
print
"正在设置服务器标识为:%s-%s"
%
(platformid, options.platform)
cfd
=
open
(ini,
'w'
)
conf
=
ConfigParser.ConfigParser()
conf.add_section(
'platforminfo'
)
conf.
set
(
'platforminfo'
,
'name'
,options.platform)
conf.
set
(
'platforminfo'
,
'id'
,platformid)
conf.write(cfd)
cfd.close()
break
sys.exit(
0
)
if
options.
id
and
options.ver
and
options.action:
cf
=
ConfigParser.ConfigParser()
cf.read(ini)
platform
=
cf.get(
'platforminfo'
,
'name'
)
platformid
=
cf.get(
'platforminfo'
,
'id'
)
cqby
=
Cqby(options.ver, platform, platformid, options.
id
)
run_function
=
getattr
(cqby,options.action)
if
options.action
in
[
'updateDB'
,]:
run_function(
'%s/server/sql/%s'
%
(options.ver,options.sql))
else
:
run_function()
else
:
parser.error(err_msg)