#!/usr/bin/python#-*- coding: UTF-8 -*-
importos,time,subprocess,shutil
defaultAppName="project.haha.com" #项目名
defaultStaticFolderName="Uploads" #用户上传静态文件夹默认名
appOwner="www:www" #默认文件所有者
defaultAppParentPath="/data/wwwroot/" #项目所在目录
defaultAppPath=defaultAppParentPath+defaultAppName #项目路径
defaultAppStaticPath=defaultAppParentPath+defaultAppName+"."+defaultStaticFolderName #项目的特殊资源目录
newFileDir="" #上传文件所在路径
defaultNewFile="upload.zip" #上传文件名
newFile="" #根据用户输入判断
factoryDir=defaultAppParentPath+"/factoryDir" #存放上传的zip文件
newFileUnzipedWorkDir=factoryDir+"/"+"unziped" #在此目录中对上传文件进行解压等操作,以防万一
appBackDir=defaultAppParentPath+"/appback/"+defaultAppName+"/" #项目的备份文件夹
appStoreParent=defaultAppParentPath+"appstore/" #项目版本库的上级文件夹
appStore=appStoreParent+defaultAppName+"/" #项目版本库
appCleanRuntimeDir=["/Runtime/Cache","/Runtime/Data","/Runtime/Temp"] #需要清除的缓存路径
timeSign=time.strftime("%a-%b-%d-%H-%M-%S-%Y", time.localtime()) #随后文件中使用的时间标记(如版本号)
#确定上传文件所在目录并验证
defjudgePath():globalnewFileDir,defaultAppPathprint "压缩包默认已上传至"+defaultAppPath
newFileDir=raw_input("如果是以上目录,请press enter,如果不是,请输入存放目录:")if newFileDir=="":
newFileDir=defaultAppPathif os.path.isdir(newFileDir)==False:print "亲,目录并不存在啊 ( >﹏<。)"
returnjudgePath()if os.access(newFileDir, os.W_OK)==False:print "亲,我木有权限进入:"+newFileDir+"( >﹏<。)"
returnjudgePath()else:return os.path.abspath(newFileDir)+"/" #abspath:返回path规范化的绝对路径
#确定上传的文件名并验证
defjudegeNewFile():globalnewFile
newFile=raw_input("默认zip文件是"+defaultNewFile+",如果是,请press enter,如果不是,请输入文件名:")if newFile=="":
newFile=defaultNewFileif os.path.exists(newFileDir+newFile)==False:print "亲,"+newFileDir+newFile+"并不存在啊 ( >﹏<。)"
returnjudegeNewFile()if os.access(newFileDir+newFile, os.W_OK)==False:print "亲,我木有写权限:"+newFile+"( >﹏<。)"
returnjudegeNewFile()else:returnnewFile#start...#删除zip文件工作目录
if os.path.isdir(newFileUnzipedWorkDir)==True:
shutil.rmtree(newFileUnzipedWorkDir)
os.makedirs(newFileUnzipedWorkDir)print "***注意***,默认操作的项目是:"+defaultAppName#获取上传文件所在的路径
newFileDir=judgePath()#获取上传文件的名字
newFile=judegeNewFile()
filePath=newFileDir+newFile #上传文件路径
#移动文件到处理目录并改名
print "将"+newFile+"移动至"+factoryDir+"进行处理..."newFilePath=factoryDir+"/"+newFile
shutil.move(filePath,newFilePath)print "已将zip文件移动至"+newFileUnzipedWorkDir#解压文件
print "开始解压文件..."pUnzip=subprocess.Popen(["unzip",newFilePath,"-d",newFileUnzipedWorkDir], stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE)#注意,如果使用stderr但不使用stdin,那unzip时是不行的,为什么?万能的网友请告诉我
"""Popen.communicate(input=None)
Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child.
communicate() returns a tuple (stdoutdata, stderrdata).
Note that if you want to send data to the process’s stdin, you need to create the Popen object with stdin=PIPE. Similarly, to get anything other than None in the result tuple, you need to give stdout=PIPE and/or stderr=PIPE too."""tupleUnzip= pUnzip.communicate("A")if tupleUnzip[-1]=="":print "解压文件完毕"
else:print "解压出错了.错误为:"+tupleUnzip[-1]
exit()
unzipedFileList=os.listdir(newFileUnzipedWorkDir)if len(unzipedFileList)>1:print "解压后发现上传文件并不是一个文件夹,目前功能很low,请压缩整个文件夹再上传"exit()
afterUnzipedFindThisFolder=unzipedFileList[0];#解压完后,发现的文件夹名字
#把新项目文件放到版本库中
thisVerName=defaultAppName+"."+timeSign#在压缩文件处理车间处理过的文件放到appstore中并重命名
"""
tipsmv用法
格式:mv dir1 dir2
如果目录dir2不存在,将目录dir1改名为dir2;否则,将dir1移动到dir2中。"""
print "准备把处理好的解压文件放到"+appStore+"/"+thisVerName
shutil.move(newFileUnzipedWorkDir+"/"+afterUnzipedFindThisFolder,appStore+"/"+thisVerName)print "已将处理好的解压文件放到"+appStore+"/"+thisVerName#删除缓存
for dir inappCleanRuntimeDir:
absDir=appStore+"/"+thisVerName+"/"+dirif(os.path.exists(absDir)):#清理
try:
shutil.rmtree(absDir)print "已删除"+absDirexceptOSError,e:print "删除失败!!!"+str(e)else:print "缓存目录"+appStore+"/"+dir+"不存在,无法清理"
#更改文件所有者
pChown=subprocess.Popen(["chown",appOwner,appStore+"/"+thisVerName,"-R"], stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
tupleChown=pChown.communicate();if tupleChown[-1]=="":print "已将文件夹的所有者改为:"+appOwnerelse:print "更改所有者失败.错误为:"+tupleChown[-1]
exit()#创建软连接
print "开始创建软链接"
#1.创建整个项目的软链接pLn=subprocess.Popen(["ln","-sfn",appStore+"/"+thisVerName,defaultAppPath], stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
tupleLn=pLn.communicate()if tupleLn[-1]=="":print "已将"+defaultAppName+"软链接到:"+appStore+"/"+thisVerNameelse:print "创建软链接错误.错误为:"+tupleChown[-1]
exit()#2.创建特殊目录软连接
shutil.move(appStore+"/"+thisVerName+"/"+defaultStaticFolderName,appStore+"/"+thisVerName+"/"+defaultStaticFolderName+".bak")if (os.path.exists(defaultAppStaticPath)==False):print "发现"+defaultAppStaticPath+"不存在,准备复制"os.makedirs(defaultAppStaticPath)#TODO:这里是异步,因此需要等待一秒,有待改进
time.sleep(1)print "准备复制的文件夹为"+appStore+"/"+thisVerName+"/"+defaultStaticFolderName+".bak"
print "最终目录为"+defaultAppStaticPath#由于subprocess中无法识别星号*,所以暂时放弃了
#cp -R ./Public.bak/* /webserver/wwwroot/Public
#pCpStatic=subprocess.Popen(["cp","-R",appStore+"/"+thisVerName+"/"+defaultStaticFolderName+".bak"+"/*",defaultAppStaticPath], stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
#tupleCpStatic = pCpStatic.communicate()
#if tupleCpStatic[-1]=="":
#print "已将"+appStore+"/"+thisVerName+"/"+defaultStaticFolderName+"复制到链接到:"+defaultAppStaticPath
#else:
#print "复制错误.错误为:"+tupleCpStatic[-1]
#exit()
os.popen("cp -R"+appStore+"/"+thisVerName+"/"+defaultStaticFolderName+".bak"+"/*"+defaultAppStaticPath)
pLnStatic=subprocess.Popen(["ln","-sfn",defaultAppStaticPath,appStore+"/"+thisVerName+"/"+defaultStaticFolderName], stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
tupleLnStatic=pLnStatic.communicate()if tupleLnStatic[-1]=="":print "已将"+defaultAppStaticPath+"软链接到:"+appStore+"/"+thisVerName+"/"+defaultStaticFolderNameelse:print "特殊目录创建软链接错误.错误为:"+tupleLnStatic[-1]
exit()"""TODO:
1.严格限制各个文件夹权限,满足访问的基础上,尽可能最小化权限
2.解压后确定是根目录
1.当前项目配置中的app_debug检测"""