UNPKG

4.28 kBJavaScriptView Raw
1var cluster = require('cluster');
2var forever = require('forever');
3var path = require('path');
4var fs = require('fs');
5var yaml = require('js-yaml');
6
7if (/versions\/\d{4}-\d{2}-\d{2},\d{2}-\d{2},[a-z0-9]{7}$/.test(process.cwd())) {
8 process.chdir('../..');
9} else if (/current$/.test(process.cwd())) {
10 process.chdir('..');
11}
12
13var project_root = process.env.PROJECT_ROOT;
14if (process.env.FIX_PROJECT_ROOT !== 'true') {
15 if (/versions\/\d{4}-\d{2}-\d{2},\d{2}-\d{2},[a-z0-9]{7}$/.test(project_root)) {
16 project_root = path.resolve(project_root, '..', '..', 'current');
17 }
18}
19project_root = path.relative(process.cwd(), project_root);
20if (!project_root) {
21 project_root = '.';
22}
23var config = yaml.safeLoad(fs.readFileSync(project_root + '/deploy.yaml', 'utf-8'));
24
25function fixScript(script) {
26 // script가 버전 디렉토리를 가리키는 경우 프로젝트 디렉토리로 변경한다
27 return script.replace(/\/versions\/\d{4}-\d{2}-\d{2},\d{2}-\d{2},[a-z0-9]{7}\//, '/');
28}
29
30function findScript(script) {
31 return new Promise(function (resolve) {
32 forever.list(false, function (error, list) {
33 if (list) {
34 list = list.filter(function (p) {
35 return p.file===script;
36 });
37 }
38 if (list && list.length>0) {
39 resolve(list[0].pid);
40 } else {
41 resolve(null);
42 }
43 });
44 });
45}
46
47function checkWorker(worker) {
48 return new Promise(function (resolve, reject) {
49 cluster.setupMaster()
50 cluster.settings.exec = __dirname + '/run_app.js';
51 cluster.settings.args = [project_root, project_root + '/app/' + worker.app];
52 cluster.settings.silent = true;
53 var child = cluster.fork({WORKER_NUM: 9999, PORT: 9999});
54 var output = [];
55 var timer = setTimeout(function () {
56 child.kill('SIGTERM');
57 var error = new Error('check failed (timeout) - ' + worker.app);
58 error.output = Buffer.concat(output).toString();
59 reject(error);
60 }, 30000);
61 child.process.stdout.on('data', function (data) {
62 output.push(data);
63 });
64 child.process.stderr.on('data', function (data) {
65 output.push(data);
66 });
67 child.once('listening', function () {
68 clearTimeout(timer);
69 child.kill('SIGTERM');
70 resolve();
71 });
72 child.once('exit', function () {
73 clearTimeout(timer);
74 child.kill('SIGTERM');
75 var error = new Error('check failed (exit) - ' + worker.app);
76 error.output = Buffer.concat(output).toString();
77 reject(error);
78 });
79 });
80}
81
82function checkWorkers(workers) {
83 return Promise.all(workers.map(checkWorker))
84 .catch(function (error) {
85 console.log('checkWorkers failed by', error.message);
86 console.log(error.output.replace(/^/gm, ' '));
87 process.exit(1);
88 });
89}
90
91function check() {
92 if (!config.workers) {
93 console.log('No workers to start');
94 return
95 }
96 checkWorkers(config.workers)
97}
98
99function start() {
100 if (!config.workers) {
101 console.log('No workers to start');
102 return
103 }
104 var script = path.resolve(__dirname, 'server.js');
105 script = fixScript(script);
106 findScript(script)
107 .then(function (pid) {
108 if (pid) {
109 forever.log.info('Reload script: ' + script);
110 forever.kill(pid, false, 'SIGHUP', function () {});
111 } else {
112 forever.log.info('Start script: ' + script);
113 options = {
114 minUptime: 10000,
115 spinSleepTime: 10000,
116 args: ['-l']
117 };
118 forever.startDaemon(script, options);
119 }
120 })
121};
122
123function stop() {
124 var script = path.resolve(__dirname, 'server.js');
125 script = fixScript(script);
126 forever.log.info('Stop script: ' + script);
127 forever.stop(script).on('error', function () {
128 }).on('stop', function () {
129 });
130};
131
132function sendSignal(signal) {
133 var script = path.resolve(__dirname, 'server.js');
134 script = fixScript(script);
135 findScript(script)
136 .then(function (pid) {
137 if (pid) {
138 forever.kill(pid, false, signal, function () {});
139 }
140 });
141};
142
143if (require.main === module) {
144 if (process.argv[2] === 'check') {
145 check();
146 } else if (process.argv[2] === 'start') {
147 start();
148 } else if (process.argv[2] === 'stop') {
149 stop();
150 } else if (process.argv[2] === 'sendSignal') {
151 sendSignal(process.argv[3]);
152 }
153}