mirror of
https://github.com/HackPlan/RootPanel.git
synced 2026-01-13 07:01:20 +08:00
资源限制初稿
This commit is contained in:
@@ -50,7 +50,7 @@ module.exports =
|
||||
|
||||
plugins:
|
||||
linux:
|
||||
cycle: 30 * 1000
|
||||
monitor_cycle: 30 * 1000
|
||||
|
||||
mysql:
|
||||
connection:
|
||||
|
||||
@@ -3,21 +3,27 @@ fs = require 'fs'
|
||||
|
||||
config = require '../../config.coffee'
|
||||
|
||||
mAccount = require '../../core/model/account'
|
||||
|
||||
REDIS_KEY = 'rp:linux:resources_usage'
|
||||
REDIS_OVERVIEW = 'rp:linux:overview'
|
||||
ITEM_IN_RESOURCES_LIST = 3600 * 1000 / config.plugins.linux.monitor_cycle
|
||||
|
||||
last_plist = []
|
||||
passwd_cache = {}
|
||||
|
||||
exports.run = ->
|
||||
setInterval exports.monitoring, config.plugins.linux.cycle
|
||||
setInterval exports.monitoring, config.plugins.linux.monitor_cycle
|
||||
|
||||
exports.loadPasswd = (callback) ->
|
||||
fs.readFile '/etc/passwd', (err, content) ->
|
||||
content = content.split '\n'
|
||||
content = content.toString().split '\n'
|
||||
|
||||
passwd_cache = {}
|
||||
|
||||
for line in content
|
||||
if line
|
||||
[username, , uid] = line.split ':'
|
||||
[username, passwd, uid] = line.split ':'
|
||||
passwd_cache[uid] = username
|
||||
|
||||
callback()
|
||||
@@ -34,34 +40,111 @@ exports.monitoring = ->
|
||||
rx = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)$/
|
||||
result = rx.exec item
|
||||
return {
|
||||
user: result[1]
|
||||
user: ->
|
||||
if passwd_cache[result[1]]
|
||||
return passwd_cache[result[1]]
|
||||
else
|
||||
return result[1]
|
||||
pid: result[2]
|
||||
cpu_per: result[3]
|
||||
mem_per: result[4]
|
||||
vsz: result[5]
|
||||
rss: result[6]
|
||||
rss: parseInt result[6]
|
||||
tty: result[7]
|
||||
stat: result[8]
|
||||
start: result[9]
|
||||
time: result[10]
|
||||
time: do ->
|
||||
[minute, second] = result[10].split ':'
|
||||
return parseInt(minute) * 60 + parseInt(second)
|
||||
command: result[11]
|
||||
}
|
||||
|
||||
async.parallel [
|
||||
(callback) ->
|
||||
cpu: (callback) ->
|
||||
exports.monitoringCpu plist, callback
|
||||
]
|
||||
|
||||
last_plist = plist
|
||||
memory: (callback) ->
|
||||
exports.monitoringMemory plist, callback
|
||||
|
||||
], (err, result) ->
|
||||
app.redis.get REDIS_KEY, (err, resources_usage_list) ->
|
||||
resources_usage_list = JSON.parse resources_usage_list
|
||||
resources_usage_list.push result
|
||||
resources_usage_list = _.last resources_usage_list, ITEM_IN_RESOURCES_LIST
|
||||
|
||||
account_usage = {}
|
||||
|
||||
addAccountUsage = (account_name, type, value) ->
|
||||
account_usage[account_name] ?= {}
|
||||
|
||||
if account_usage[account_name][type]
|
||||
account_usage[account_name][type] += value
|
||||
else
|
||||
account_usage[account_name][type] += value
|
||||
|
||||
|
||||
for item in resources_usage_list
|
||||
for account_name, cpu_usage of item.cpu
|
||||
addAccountUsage account_name, 'cpu', cpu_usage
|
||||
|
||||
for account_name, memory_usage of item.memory
|
||||
addAccountUsage account_name, 'memory', memory_usage
|
||||
|
||||
for account_name, usage of account_usage
|
||||
usage.memory = usage.memory / (resources_usage_list.length * config.plugins.linux.monitor_cycle * 1000)
|
||||
|
||||
app.redis.setex REDIS_OVERVIEW, 60, JSON.stringify(account_usage), ->
|
||||
async.each _.keys(account_usage), (account_name) ->
|
||||
mAccount.byUsername account_name, (err, account) ->
|
||||
if account_usage[account_name].cpu > account.attribute.resources_limit.cpu
|
||||
child_process.exec "pkill -SIGKILL -u #{account_name}", ->
|
||||
|
||||
if account_usage[account_name].memory > account.attribute.resources_limit.memory
|
||||
child_process.exec "pkill -SIGKILL -u #{account_name}", ->
|
||||
|
||||
callback()
|
||||
, ->
|
||||
app.redis.set REDIS_KEY, JSON.stringify(resources_usage_list), ->
|
||||
last_plist = plist
|
||||
|
||||
exports.monitoringCpu = (plist, callback) ->
|
||||
exist_process = _.filter plist, (item) ->
|
||||
total_time = {}
|
||||
|
||||
findLastProcess = (process) ->
|
||||
return _.find last_plist, (i) ->
|
||||
return i.pid == item.pid and i.user == item.user and i.command == item.command
|
||||
return i.pid == process.pid and i.user == process.user and i.command == process.command
|
||||
|
||||
addTime = (account_name, time) ->
|
||||
if total_time[account_name]
|
||||
total_time[account_name] += time
|
||||
else
|
||||
total_time[account_name] = time
|
||||
|
||||
exist_process = _.filter plist, (item) ->
|
||||
return findLastProcess item
|
||||
|
||||
new_process = _.fliter plist, (item) ->
|
||||
return not _.find last_plist, (i) ->
|
||||
return i.pid == item.pid and i.user == item.user and i.command == item.command
|
||||
|
||||
return not findLastProcess item
|
||||
|
||||
for item in exist_process
|
||||
last_process = findLastProcess item
|
||||
addTime item.user, last_process.time - item.time
|
||||
|
||||
for item in new_process
|
||||
addTime item.user, item.time
|
||||
|
||||
callback null, total_time
|
||||
|
||||
exports.monitoringMemory = (plist, callback) ->
|
||||
total_memory = 0
|
||||
|
||||
addMemory = (account_name, menory) ->
|
||||
if total_memory[account_name]
|
||||
total_memory[account_name] += menory
|
||||
else
|
||||
total_memory[account_name] = menory
|
||||
|
||||
for item in plist
|
||||
addMemory item.user, ((item.rss / 1024) * config.plugins.linux.monitor_cycle / 1000).toFixed()
|
||||
|
||||
callback null, total_memory
|
||||
|
||||
@@ -2,12 +2,12 @@ header Linux
|
||||
table.table.table-hover
|
||||
tbody
|
||||
tr
|
||||
td(style='width: 200px;') 2 小时 CPU 时间
|
||||
td(style='width: 200px;') 一小时 CPU 时间
|
||||
td
|
||||
.progress
|
||||
.progress-bar.progress-bar-success(role='progressbar', aria-valuenow='20', aria-valuemin='0', aria-valuemax='100', style='width: 20%;') 58 / 288 s
|
||||
.progress-bar.progress-bar-success(role='progressbar', aria-valuenow='20', aria-valuemin='0', aria-valuemax='100', style='width: 20%;') 58 / 144 s
|
||||
tr
|
||||
td 2 小时内存占用
|
||||
td 一小时内存占用
|
||||
td
|
||||
.progress
|
||||
.progress-bar.progress-bar-success(role='progressbar', aria-valuenow='85', aria-valuemin='0', aria-valuemax='100', style='width: 85%;') 23 / 27 M
|
||||
|
||||
@@ -7,8 +7,8 @@ fs = require 'fs'
|
||||
mAccount = require '../../core/model/account'
|
||||
|
||||
template =
|
||||
site_configure: fs.readFileSync './template/site_configure'
|
||||
user_configure: fs.readFileSync './template/user_configure'
|
||||
site_configure: fs.readFileSync "#{__dirname}/template/site_configure.conf"
|
||||
user_configure: fs.readFileSync "#{__dirname}/template/user_configure.conf"
|
||||
|
||||
module.exports =
|
||||
enable: (account, callback) ->
|
||||
|
||||
Reference in New Issue
Block a user