-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathviewlog.js
More file actions
146 lines (128 loc) · 3.89 KB
/
viewlog.js
File metadata and controls
146 lines (128 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env node
// node.js用サーバスクリプト
// viewlog.ejsをテンプレートファイルとして必要します。
// CentOS 6だったらEPEL有効にして、
// yum --enablerepo=epel install nodejs npm
// npm install ws ejs
// node viewlog.js
// Common
var os = require('os');
var httpPort = 3000;
var wsPort = 3001;
var wsHost = os.hostname();
var logList = [
'/var/log/httpd/access_log',
'/var/log/httpd/error_log',
'/var/log/nginx/access.log',
'/var/log/nginx/error.log',
'dummy' // ケツカンマハック
]; logList.pop(); // ケツカンマハックその2
// HTTP
var ejs = require('ejs');
var http = require('http');
// HTTP server を作る
http.createServer( function (req, res) {
res.writeHead( 200, { 'content-type': 'text/html' });
// ejs fileをレンダリング
ejs.renderFile(
__dirname + '/viewlog.ejs',
{
wsHost: wsHost,
wsPort: wsPort,
logList: logList
},
function(err, result) {
// render on success
if (!err) {
res.end(result);
}
// render or error
else {
res.end('An error occurred');
console.log(err);
}
}
);
}).listen(httpPort);
// WebSocket
var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
var WsServer = require('ws').Server;
var cp = {};
var connections = [];
// WebSocketサーバを作成する
var wss = new WsServer( { port: wsPort });
// 監視するログファイル
var file = logList[0];
// 接続時に発生するイベントをセットする (d.interceptで例外捕捉)
wss.on('connection', function(ws) {
connections.push(ws);
ws.on('close', function () {
stopWatch(ws);
connections = connections.filter(function (conn, i) {
return (conn === ws) ? false : true;
});
});
// ファイルを監視して変更があれば readAndSendを実行する
startWatch(ws, file);
// クライアントからメッセージが来たら監視するログファイルを変更する
ws.on('message', function(msg) {
// ログファイルをクライアントから直接指定できるのはセキュリティリスク高いので
// リスト番号で
var order;
order = msg.replace(/[^0-9]/g, ''); // ブラウザから送信されるはずなのは数字のみ
order = parseInt(order);
file = logList[order];
if ( path.existsSync( file ) ) {
startWatch(ws, file);
}
else {
sendLog( ws, 'not found: ' + file );
startWatch(ws, undefined);
}
});
});
// $ tail -1 で末行を取得
function readAndSend( ws, file ) {
exec('tail -1 ' + file, function( err, stdout, stderr ) {
if ( err ) throw err;
sendLog( ws, stdout );
});
}
// WebSocketを送信する
function sendLog( ws, data ) {
if ( ws.readyState === 1 )
ws.send( JSON.stringify ( data ) ); // WebSocketでデータを送信する
}
function startWatch(ws, file) {
// 現在存在するwatcherから、wsを外す
stopWatch( ws );
if ( typeof file == 'undefined' ) {
return;
}
// まだwatcherが作られていない場合
if (! ( file in cp ) ) {
cp[file] = { socket: [], };
cp[file].watcher = fs.watch( file, function( eventName, filename ) {
for ( var i = 0; i < cp[file].socket.length; i++ ) {
readAndSend( cp[file].socket[i], file);
}
});
}
// watcherからコールバックでkickされるsockを追加
cp[file].socket.push(ws);
// console.log( cp ); // 今相手しているwsクライアント情報
}
function stopWatch(sock) {
// 現在存在するwatcherから、sockを外す
for ( var key in cp ) {
cp[key].socket = cp[key].socket.filter( function( a, b ) {
return ( a === sock ) ? false : true;
});
if ( cp[key].socket.length == 0 ) { // watcherにsocketがなくなった
cp[key].watcher.close(); // watcherを止める
delete cp[key]; // 消す
}
}
}