金钱(警告)
** 状态:** 被贬值
如果您目前正在运行运行 Ubuntu 12.04 的服务器,我们强烈建议升级或迁移到支持的 Ubuntu 版本:
** 原因:** Ubuntu 12.04 已于 2017 年 4 月 28 日到期(EOL)并且不再收到安全补丁或更新。
** 参见相反:** 本指南可能仍然有用作为参考,但可能不会在其他Ubuntu版本上工作. 如果可用,我们强烈建议使用为您正在使用的Ubuntu版本撰写的指南。
介绍
一个 [daemon](http://en.wikipedia.org/wiki/Daemon_(computing)是一个程序,在背景中运行,没有控制终端. 它们通常用于提供背景服务. 例如,一个Web服务器或数据库服务器可以作为一个daemon运行。
本教程将向您展示如何使用 Node.js编写一个 DAEMON,并在您的VPS上使用 Upstart部署它。
我会专注于实施一个 标准 daemon. 我只是为了简单而使用 upstart,但是你可以写一个 System-V init脚本或使用任何你喜欢的启动你的 daemon。
要求
对于本教程,您将需要一个 Linux VPS(最好是 Ubuntu或 CentOS), Node.js和 Upstart。
Node.js 的
安装 **Node.js 的几种方法,我认为最简单的方法是使用 nvm。
或者,您可以遵循这些指南之一:
升起
Upstart在许多Linux发行版上预先安装,如果没有安装在您选择的发行版上,您应该能够从官方存储库中安装它,您也可以从源代码中编译它。
Daemons 如何工作
基本上,一个戴蒙像一个正常的过程一样开始,然后会发生以下情况:
它创建了自己的副本,因为它是孩子的过程 2 孩子从父母的过程中分离出来 3 孩子的过程关闭了其标准的文件描述器(http://en.wikipedia.org/wiki/File_descriptor)(见下文) 4 父母的过程退出 5 戴蒙在背景中继续工作
代替关闭标准文件描述器,家长进程可以打开 null device并将其附加到孩子的标准文件描述器中。
戴蒙的例子
为了这个教程,我们将创建一个简单的 ** HTTP ** 戴蒙。
我们的DAEMON将能够:
- 在背景中开始(我们将使用一个称为 **
daemon
**的模块) 2.为 HTTP服务器绑定多个工人 3.在 SIGHUP上重新启动工人 4.在 SIGTERM上终止工人 5.在 HTTP服务器启动后放下工人的特权
初步项目结构
以下是初步项目结构:
1node-simple-http-daemon/
2|
3|-- README.md
4|-- bin/
5| `-- node-simple-http-daemon
6`-- lib/
7 `-- app.js
标签: 杰森
让我们开始创建一个 package.json文件:
1$ npm init
安裝 daemon模組:
1$ npm --save install daemon
以下是包装.json 的样子:
1{
2 "name": "node-simple-http-daemon",
3 "version": "0.0.0",
4 "description": "Simple HTTP Daemon written in Node.js",
5 "main": "lib/app.js",
6 "scripts": {
7 "test": "echo \"Error: no test specified\" && exit 1",
8 "start": "node lib/app.js"
9 },
10 "author": "Fardjad Davari",
11 "license": "MIT",
12 "dependencies": {
13 "daemon": "~1.1.0"
14 }
15}
请注意,我们添加了开始 脚本,因此我们可以稍后使用npm start
命令启动应用程序。
HTTP服务器
目前,我们将创建一个简单的 HTTP服务器,该服务器开始在端口 80上聆听并对每个请求响应 Hello world
。
将以下内容放入lib/app.js文件中:
1/**
2 * lib/app.js
3 */
4
5const PORT = 80;
6const ADDRESS = '0.0.0.0';
7
8var http = require('http');
9
10var server = http.createServer(function (req, res) {
11 res.writeHead(200, {'Content-Type': 'text/plain'});
12 res.end('Hello World\n');
13});
14
15server.listen(PORT, ADDRESS, function () {
16 console.log('Server running at http://%s:%d/', ADDRESS, PORT);
17 console.log('Press CTRL+C to exit');
18});
您可以通过运行sudo npm start
来启动VPS。
DAEMON 可执行
以下是 DAEMON 可执行代码。
以下内容应放在 bin/node-simple-http-daemon中:
1#!/usr/bin/env node
2
3/**
4 * bin/node-simple-http-daemon
5 */
6
7// Everything above this line will be executed twice
8require('daemon')();
9
10var cluster = require('cluster');
11
12// Number of CPUs
13var numCPUs = require('os').cpus().length;
14
15/**
16 * Creates a new worker when running as cluster master.
17 * Runs the HTTP server otherwise.
18 */
19function createWorker() {
20 if (cluster.isMaster) {
21 // Fork a worker if running as cluster master
22 var child = cluster.fork();
23
24 // Respawn the child process after exit
25 // (ex. in case of an uncaught exception)
26 child.on('exit', function (code, signal) {
27 createWorker();
28 });
29 } else {
30 // Run the HTTP server if running as worker
31 require('../lib/app');
32 }
33}
34
35/**
36 * Creates the specified number of workers.
37 * @param {Number} n Number of workers to create.
38 */
39function createWorkers(n) {
40 while (n-- > 0) {
41 createWorker();
42 }
43}
44
45/**
46 * Kills all workers with the given signal.
47 * Also removes all event listeners from workers before sending the signal
48 * to prevent respawning.
49 * @param {Number} signal
50 */
51function killAllWorkers(signal) {
52 var uniqueID,
53 worker;
54
55 for (uniqueID in cluster.workers) {
56 if (cluster.workers.hasOwnProperty(uniqueID)) {
57 worker = cluster.workers[uniqueID];
58 worker.removeAllListeners();
59 worker.process.kill(signal);
60 }
61 }
62}
63
64/**
65 * Restarts the workers.
66 */
67process.on('SIGHUP', function () {
68 killAllWorkers('SIGTERM');
69 createWorkers(numCPUs * 2);
70});
71
72/**
73 * Gracefully Shuts down the workers.
74 */
75process.on('SIGTERM', function () {
76 killAllWorkers('SIGTERM');
77});
78
79// Create two children for each CPU
80createWorkers(numCPUs * 2);
是时候开始我们的大卫了!但是在那之前,我们应该修改我们的 app.js到 处理 SIGTERM。
将以下内容添加到 app.js 文件的末尾:
1process.on('SIGTERM', function () {
2 if (server === undefined) return;
3 server.close(function () {
4 // Disconnect from cluster master
5 process.disconnect && process.disconnect();
6 });
7});
让 DAEMON 脚本可执行:
1$ chmod +x bin/node-simple-http-daemon
其次,要把它放进去([确保没有其他东西在端口80上运行]):
1$ sudo bin/node-simple-http-daemon
你可以 确认通过通过 cURL发送一个 HTTP GET请求:
1$ curl 127.0.0.1
在进入下一步之前,让我们看看进程ID:
1$ ps -axf | grep [n]ode-simple-http-daemon | \
2 awk '{ print "pid:"$2", parent-pid:"$3 }'
样品产量:
1pid:33811, parent-pid:1
2pid:33853, parent-pid:33811
3pid:33856, parent-pid:33811
4pid:33857, parent-pid:33811
5pid:33858, parent-pid:33811
6pid:33859, parent-pid:33811
7pid:33860, parent-pid:33811
8pid:33861, parent-pid:33811
9pid:33862, parent-pid:33811
请注意,戴蒙是 ** parent-pid** 的过程。
尝试通过将 **SIGHUP ** 发送到 DAEMON 来重新启动工人:
1$ kill -HUP 33811 # (replace 33811 with the daemon PID)
现在,如果你再次列出PID,你应该能够看到新的工人流程与新的PID。
要阻止戴蒙,只需运行:
1$ kill -TERM 33811 # (replace 33811 with the daemon PID)
放弃特权
我们只需要让员工在VPS开始后放弃他们的特权。
在 app.js中修改server.listen()
呼叫,这样它会读到:
1server.listen(PORT, ADDRESS, function () {
2 console.log('Server running at http://%s:%d/', ADDRESS, PORT);
3 console.log('Press CTRL+C to exit');
4
5 // Check if we are running as root
6 if (process.getgid() === 0) {
7 process.setgid('nobody');
8 process.setuid('nobody');
9 }
10});
这就是戴蒙的部分。
现在您可以安装整个系统:
1$ sudo npm link
升起
创建一个文件在 /etc/init/node-simple-http-daemon.conf
下列内容:
1# /etc/init/node-simple-http-daemon.conf
2
3start on started network
4stop on stopping network
5
6respawn
7expect daemon
8
9exec https-proxy-daemon
现在你可以:
1$ sudo start node-simple-http-daemon # Start the job
2$ initctl --system node-simple-http-daemon # Check the job status
3$ sudo reload node-simple-http-daemon # Send SIGHUP (restart the workers)
4$ sudo stop node-simple-http-daemon # Stop the job
下一步
你可能想修改大象,以放弃生育工人,当他们被杀害太频繁(旋转)。
我不能足够强调在你的应用程序中有足够的日志的重要性,请确保检查 node-bunyan。