宝塔nodejs项目自动化部署
- 首先宝塔要安装一下软件
1.1 宝塔SSH终端 V1.0
1.2 宝塔WebHook工具 V1.2
1.3 PM2管理器 V4.2.3 - 打开宝塔SSH
2.1 cd到自己要下载保存项目的目录,GitClone项目
2.2 然后cd进拷贝下来的项目
2.3 然后输入 git config --global credential.helper store
2.4 执行 git pull 拉去代码 - 打开宝塔WebHook
3.1 点击添加
3.2 名称要和自己项目的英文地址一致(重要)
3.3 执行脚本粘贴下方代码,并修改自己的git名称和项目下载的目录
#!/bin/bash
echo ""
#输出当前时间
date --date='0 days ago' "+%Y-%m-%d %H:%M:%S"
echo "Start"
#判断宝塔WebHook参数是否存在
if [ ! -n "$1" ];
then
echo "param参数错误"
echo "End"
exit
fi
#git项目路径
#路径自己定义
gitPath="/www/wwwroot/项目路径/$1"
#git 下载地址(这里的$1表示添加的时候的名称)
gitHttp="https://gitee.com/自己的git名称/$1.git"
echo "Web站点路径:$gitPath"
#判断项目路径是否存在
if [ -d "$gitPath" ]; then
cd $gitPath
#判断是否存在git目录
if [ ! -d ".git" ]; then
echo "在该目录下克隆 git"
sudo git clone $gitHttp gittemp
sudo mv gittemp/.git .
sudo rm -rf gittemp
fi
echo "拉取最新的项目文件"
sudo git reset --hard origin/master
sudo git pull
echo "设置目录权限"
sudo chown -R www:www $gitPath
echo "End"
exit
else
echo "该项目路径不存在"
echo "新建项目目录"
mkdir $gitPath
cd $gitPath
#判断是否存在git目录
if [ ! -d ".git" ]; then
echo "在该目录下克隆 git"
sudo git clone $gitHttp gittemp
sudo mv gittemp/.git .
sudo rm -rf gittemp
fi
echo "拉取最新的项目文件"
sudo git reset --hard origin/master
sudo git pull
echo "设置目录权限"
sudo chown -R www:www $gitPath
echo "End"
exit
fi
3.4 点击查看秘钥
3.5 复制GET/POST下面的https开始至param=aaa结束的部分,并且param=后面的aaa改成自己的项目英文名称
- 打开gitee码云
4.1 进入自己的项目点击管理,点击webhook,地址里粘贴刚才的地址保存 - 在宝塔的软件市场 找到PM2 点击旁边的文件夹图标 进入pm2的根文件(路径应该是/www/server/panel/plugin/pm2)
5.1 修改pm2_main.py文件 删除pm2_main.pyc文件
#!/usr/bin/python
#coding: utf-8
#-----------------------------
# PM2管理插件
#-----------------------------
import sys,os,psutil
os.chdir('/www/server/panel')
sys.path.append("class/")
import public,re,json
class pm2_main:
__SR = None
__path = '/www/server/panel/plugin/pm2/list/'
def __init__(self):
s_path = '/www'
if os.path.islink(s_path):
s_path=os.readlink(s_path) + '/server'
else:
s_path += '/server'
if os.path.islink(s_path):
s_path = os.readlink(s_path)
self.__SR = '''#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
export HOME=/root
export NVM_NODEJS_ORG_MIRROR=http://npm.taobao.org/mirrors/node
export NVM_DIR="{}/nvm"
source /www/server/nvm/nvm.sh ; '''.format(s_path)
#列表
def List(self,get):
try:
tmp = public.ExecShell(self.__SR + "pm2 list -m|grep -v 'pm2 list'|grep -v 'In memory PM2'|grep -v 'Local PM2'")
appList = tmp[0].strip().split('+---')
result = []
tmp = public.ExecShell('lsof -c node -P|grep LISTEN')
plist = tmp[0].split('\n')
for app in appList:
try:
if not app: continue
tmp2 = re.findall(r"([\w ]+):(.+)",app)
tmp3 = {}
for t in tmp2:
tmp3[t[0].strip()] = t[1].strip()
tmp2 = tmp3
appInfo = {}
appInfo['name'] = app.split('\n')[0].strip()
appInfo['id'] = tmp2['pm2 id']
appInfo['mode'] = tmp2['mode']
appInfo['pid'] = int(tmp2['pid'])
appInfo['status'] = tmp2['status']
appInfo['restart'] = tmp2['restarted']
appInfo['uptime'] = tmp2['uptime']
appInfo['cpu'] = 0
if appInfo['pid'] and appInfo['pid'] != 'N/A':
try:
appInfo['cpu'] = psutil.Process(appInfo['pid']).cpu_percent(0.3)
except: appInfo['cpu'] = 0
appInfo['mem'] = tmp2['memory usage']
appInfo['user'] = 'root'
appInfo['watching'] = tmp2['watching']
appInfo['port'] = 'OFF'
appInfo['path'] = 'OFF'
for p in plist:
ptmp = p.split()
if len(ptmp) < 8: continue
if ptmp[1] == str(appInfo['pid']): appInfo['port'] = ptmp[8].split(':')[1].split('->')[0]
if os.path.exists(self.__path + appInfo['name']): appInfo['path'] = public.readFile(self.__path + appInfo['name'])
result.append(appInfo)
except: continue
return result
except:
return public.returnMsg(False,'请检查pm2是否正常!'+public.get_error_info())
#获取已安装库
def GetMod(self,get):
tmp = public.ExecShell(self.__SR + "npm list --depth=0 -global --json|grep -v '/www/server/nvm'")
modList = json.loads(tmp[0])
result = []
for m in modList['dependencies'].keys():
mod = {}
mod['name'] = m
mod['version'] = modList['dependencies'][m]['version']
result.append(mod)
return result
#安装库
def InstallMod(self,get):
os.system(self.__SR + 'npm install ' + get.mname + ' -g')
return public.returnMsg(True,'安装成功!')
#卸载库
def UninstallMod(self,get):
MyNot=['pm2','npm']
if get.mname in MyNot: return public.returnMsg(False,'不能卸载['+get.mname+']')
os.system(self.__SR + 'npm uninstall ' + get.mname + ' -g')
return public.returnMsg(True,'卸载成功!')
#获取Node版本列表
def Versions(self,get):
result = {}
rep = r'v\d+\.\d+\.\d+'
tmp = public.ExecShell(self.__SR+'nvm ls-remote --lts|grep -v v0|grep -v iojs')
result['list'] = re.findall(rep,tmp[0])
tmp = public.ExecShell(self.__SR + "nvm version")
result['version'] = tmp[0].strip()
print(tmp)
return result
#切换Node版本
def SetNodeVersion(self,get):
version = get.version.replace('v','')
estr = '''
export NVM_NODEJS_ORG_MIRROR=http://npm.taobao.org/mirrors/node && nvm install %s
nvm use --delete-prefix %s
nvm alias default %s
oldreg=`npm get registry`
npm config set registry http://registry.npm.taobao.org/
npm install pm2 -g
npm config set registry $oldreg
''' % (version,version,version)
os.system(self.__SR + estr)
return public.returnMsg(True,'已切换至['+get.version+']')
#添加
def Add(self,get):
#get.pname = get.pname.encode('utf-8');
if not re.match(r"^\w+$",get.pname):
return public.returnMsg(False,'项目名称不能包含特殊符号!')
runFile = (get.path + '/' + get.run).replace('//','/')
if not os.path.exists(runFile): return public.returnMsg(False,'指定文件不存在!')
Nlist = self.List(get)
for node in Nlist:
if get.pname == node['name']: return public.returnMsg(False,'指定项目名称已经存在!')
if os.path.exists(get.path + '/package.json') and not os.path.exists(get.path + '/package-lock.json'): os.system(self.__SR + "cd " + get.path + ' && npm install -s')
os.system(self.__SR + 'cd '+get.path+' && pm2 start ' + runFile + ' --name "'+get.pname+'" --watch|grep ' + get.pname)
public.ExecShell(self.__SR + 'pm2 save && pm2 startup')
if not os.path.exists(self.__path): os.system('mkdir -p ' + self.__path)
public.writeFile(self.__path + get.pname,get.path)
return public.returnMsg(True,'ADD_SUCCESS')
#启动
def Start(self,get):
#get.pname = get.pname.encode('utf-8');
result = public.ExecShell(self.__SR + 'pm2 start "' + get.pname + '" --watch|grep ' + get.pname)[0]
if result.find('online') != -1: return public.returnMsg(True,'项目['+get.pname+']已启动!')
return public.returnMsg(False,'项目['+get.pname+']启动失败!')
#停止
def Stop(self,get):
#get.pname = get.pname.encode('utf-8');
result = public.ExecShell(self.__SR + 'pm2 stop "' + get.pname + '"|grep ' + get.pname)[0]
if result.find('stoped') != -1: return public.returnMsg(True,'项目['+get.pname+']已停止!')
return public.returnMsg(True,'项目['+get.pname+']停止失败!')
#重启
def Restart(self,get):
#get.pname = get.pname.encode('utf-8');
result = public.ExecShell(self.__SR + 'pm2 restart "' + get.pname + '"')[0]
if result.find('✓') != -1: return public.returnMsg(True,'项目['+get.pname+']已重启!')
return public.returnMsg(False,'项目['+get.pname+']重启失败!')
#重载
def Reload(self,get):
#get.pname = get.pname.encode('utf-8');
result = public.ExecShell(self.__SR + 'pm2 reload "' + get.pname + '"')[0]
if result.find('✓') != -1: return public.returnMsg(True,'项目['+get.pname+']已重载!')
return public.returnMsg(False,'项目['+get.pname+']重载失败!')
#删除
def Delete(self,get):
# get.pname = get.pname.encode('utf-8');
result = public.ExecShell(self.__SR + 'pm2 stop "'+get.pname+'" && pm2 delete "' + get.pname + '"|grep "' + get.pname+'"')[0]
if result.find('✓') != -1:
public.ExecShell(self.__SR + 'pm2 save && pm2 startup')
if os.path.exists(self.__path + get.pname): os.remove(self.__path + get.pname)
return public.returnMsg(True,'DEL_SUCCESS')
return public.returnMsg(False,'DEL_ERROR')
#获取日志
def GetLogs(self,get):
path = '/root/.pm2/pm2.log'
if not os.path.exists(path): return '当前没有日志'
return public.readFile(path)
if __name__ == "__main__":
p = pm2_main()
print(p.List(None))
- 重启服务器
- 打开pm2 添加自己的nodejs项目就好了 然后git提交就能自动部署了(提示:如果没有重新启动nodejs,可以手动暂停项目后点击启动即可)