feat: 添加 poweroff/temp-status/zram-swap 包
- luci-app-poweroffdevice: LuCI 软关机按钮(来自 sirpdboy) - luci-app-temp-status: RK3588 实时温度监控(CPU/GPU/NPU) - zram-swap: 压缩交换内存,Docker 多容器时缓解 OOM
This commit is contained in:
parent
b1d30a8e62
commit
8a5a616718
19
package/diy/luci-app-poweroffdevice/Makefile
Normal file
19
package/diy/luci-app-poweroffdevice/Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#
|
||||||
|
# provides Web UI to shut down (power off) your device.
|
||||||
|
# Copyright (C) 2022-2026 sirpdboy <herboy2008@gmail.com>
|
||||||
|
# This is free software, licensed under the GNU General Public License v3.
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
NAME:=poweroffdevice
|
||||||
|
PKG_NAME:=luci-app-$(NAME)
|
||||||
|
LUCI_TITLE:=LuCI support for poweroffdevice Router
|
||||||
|
LUCI_DESCRIPTION:=provides Web UI to shut down (power off) your device.
|
||||||
|
|
||||||
|
LUCI_PKGARCH:=all
|
||||||
|
PKG_VERSION:=2
|
||||||
|
PKG_RELEASE:=7
|
||||||
|
|
||||||
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|
||||||
|
# call BuildPackage - OpenWrt buildroot signature
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
'use strict';
|
||||||
|
'require view';
|
||||||
|
'require ui';
|
||||||
|
'require fs';
|
||||||
|
|
||||||
|
return view.extend({
|
||||||
|
render: function() {
|
||||||
|
return E([
|
||||||
|
E('div', { class: 'cbi-section' }, [
|
||||||
|
E('h2', { class: 'cbi-section-title' }, _('PowerOff')),
|
||||||
|
E('div', { class: 'cbi-section-descr' }, _('Turn off the power to the device you are using')),
|
||||||
|
E('hr', { style: 'margin: 15px 0' }),
|
||||||
|
E('div', { style: ' padding: 20px 0' }, [
|
||||||
|
E('button', {
|
||||||
|
class: 'btn cbi-button cbi-button-negative important',
|
||||||
|
style: 'padding: 0.5rem 1rem;font-size: 1.2em;font-weight: bold;border-radius: 4px;box-shadow: 0 2px 5px rgba(0,0,0,0.2);',
|
||||||
|
click: ui.createHandlerFn(this, 'handlePowerOff')
|
||||||
|
}, _('⚠️ Perform Power Off'))
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
handlePowerOff: function() {
|
||||||
|
return ui.showModal(_('⚠️ PowerOff Device'),
|
||||||
|
E('div', { style: 'min-width: 350px' }, [
|
||||||
|
E('div', { class: 'alert-message warning', style: 'margin: 0 0 15px 0; padding: 10px; background: #f0ad4e' }, [
|
||||||
|
E('h4', { style: 'margin: 0 0 5px 0; ' }, _('Warning!')),
|
||||||
|
E('p', { style: 'margin: 0; ' }, _('This action will immediately turn off the power to your device. Make sure to save all your work before proceeding.'))
|
||||||
|
]),
|
||||||
|
|
||||||
|
E('div', { style: ' border-radius: 4px; padding: 15px; margin-bottom: 15px' }, [
|
||||||
|
E('p', { style: 'margin: 0 0 10px 0; font-weight: bold' }, _('Before you continue:')),
|
||||||
|
E('ul', { style: 'margin: 0; padding-left: 20px' }, [
|
||||||
|
E('li', { style: 'margin-bottom: 5px' }, _('Save all unsaved settings')),
|
||||||
|
E('li', { style: 'margin-bottom: 5px' }, _('Check if other users are active')),
|
||||||
|
E('li', _('The device needs to be manually turned on'))
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
|
||||||
|
E('div', { class: 'right', style: 'margin-top: 20px; padding-top: 15px; border-top: 1px solid #ddd' }, [
|
||||||
|
E('button', {
|
||||||
|
'class': 'btn cbi-button cbi-button-apply',
|
||||||
|
'style': 'margin-right: 10px; ',
|
||||||
|
'click': ui.hideModal
|
||||||
|
}, _('Cancel')),
|
||||||
|
E('button', {
|
||||||
|
'class': 'btn cbi-button cbi-button-negative',
|
||||||
|
'style': ' font-weight: bold;',
|
||||||
|
'click': ui.createHandlerFn(this, function() {
|
||||||
|
ui.hideModal();
|
||||||
|
|
||||||
|
// Show powering off modal
|
||||||
|
ui.showModal(_('Powering Off'),
|
||||||
|
E('div', { style: 'text-align: center; padding: 30px; min-width: 300px' }, [
|
||||||
|
E('div', {
|
||||||
|
class: 'spinning',
|
||||||
|
style: 'font-size: 48px; margin-bottom: 20px; color: #f0ad4e;'
|
||||||
|
}, '⚡'),
|
||||||
|
E('h3', { style: 'margin: 0 0 15px 0' }, _('Powering off device...')),
|
||||||
|
E('p', { style: 'color: #666; margin: 0' },
|
||||||
|
_('The device should power off within a few seconds. If the device remains on, you may need to perform a manual shutdown.'))
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Execute poweroff command
|
||||||
|
return fs.exec('/sbin/poweroff').catch(function(e) {
|
||||||
|
ui.hideModal();
|
||||||
|
ui.addNotification(null,
|
||||||
|
E('div', { style: 'padding: 10px' }, [
|
||||||
|
E('h4', { style: 'color: #d9534f; margin: 0 0 5px 0' }, _('Error!')),
|
||||||
|
E('p', { style: 'margin: 0' }, e.message)
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}, _('Confirm Power Off'))
|
||||||
|
])
|
||||||
|
])
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSaveApply: null,
|
||||||
|
handleSave: null,
|
||||||
|
handleReset: null
|
||||||
|
});
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
#
|
||||||
|
# provides Web UI to shut down (power off) your device.
|
||||||
|
# routers are listed at https://github.com/sirpdboy/luci-app-poweroffdevice
|
||||||
|
# This is free software, licensed under the GNU General Public License v3.
|
||||||
|
|
||||||
|
msgid "PowerOff"
|
||||||
|
msgstr "关机"
|
||||||
|
|
||||||
|
msgid "PowerOff Device"
|
||||||
|
msgstr "设备关机"
|
||||||
|
|
||||||
|
msgid "Perform Power Off"
|
||||||
|
msgstr "执行关机"
|
||||||
|
|
||||||
|
msgid "Turn off the power to the device you are using"
|
||||||
|
msgstr "关闭您正在使用的设备的电源"
|
||||||
|
|
||||||
|
msgid "WARNING: Power off might result in a reboot on a device which not support power off."
|
||||||
|
msgstr "警告:对于不支持关机的设备,关机可能会导致重新启动."
|
||||||
|
|
||||||
|
msgid "PowerOffing..."
|
||||||
|
msgstr "正在关机..."
|
||||||
|
|
||||||
|
msgid "Device shutdown complete!"
|
||||||
|
msgstr "设备关机完毕!"
|
||||||
|
|
||||||
|
msgid "PowerOff failed"
|
||||||
|
msgstr "关机失败"
|
||||||
|
|
||||||
|
msgid "The device is shutting down..."
|
||||||
|
msgstr "设备正在关闭..."
|
||||||
|
|
||||||
|
msgid "The device may have powered off. If not, check manually."
|
||||||
|
msgstr "设备已断电。如果没有,请手动操作。"
|
||||||
|
|
||||||
|
msgid "Confirm"
|
||||||
|
msgstr "确认"
|
||||||
|
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
#
|
||||||
|
# provides Web UI to shut down (power off) your device.
|
||||||
|
# routers are listed at https://github.com/sirpdboy/luci-app-poweroffdevice
|
||||||
|
# This is free software, licensed under the GNU General Public License v3.
|
||||||
|
|
||||||
|
msgid "PowerOff"
|
||||||
|
msgstr "关机"
|
||||||
|
|
||||||
|
msgid "⚠️ PowerOff Device"
|
||||||
|
msgstr "⚠️ 设备关机"
|
||||||
|
|
||||||
|
msgid "⚠️ Perform Power Off"
|
||||||
|
msgstr "⚠️ 执行关机"
|
||||||
|
|
||||||
|
msgid "Turn off the power to the device you are using"
|
||||||
|
msgstr "关闭您正在使用的设备的电源"
|
||||||
|
|
||||||
|
msgid "This action will immediately turn off the power to your device. Make sure to save all your work before proceeding."
|
||||||
|
msgstr "此操作将立即关闭设备的电源。在继续之前,请确保保存所有工作"
|
||||||
|
|
||||||
|
msgid "Powering off device..."
|
||||||
|
msgstr "正在关机..."
|
||||||
|
|
||||||
|
msgid "Confirm Power Off"
|
||||||
|
msgstr "确认关机"
|
||||||
|
|
||||||
|
msgid "Warning!"
|
||||||
|
msgstr "警告"
|
||||||
|
|
||||||
|
msgid "Before you continue:"
|
||||||
|
msgstr "继续关机之前:"
|
||||||
|
|
||||||
|
msgid "Save all unsaved settings"
|
||||||
|
msgstr "保存所有未保存的设置"
|
||||||
|
|
||||||
|
msgid "Check if other users are active"
|
||||||
|
msgstr "检查其他用户是否处于活动状态"
|
||||||
|
|
||||||
|
msgid "The device needs to be manually turned on"
|
||||||
|
msgstr "设备需要手动开机"
|
||||||
|
|
||||||
|
msgid "Powering Off"
|
||||||
|
msgstr "关机中"
|
||||||
|
|
||||||
|
msgid "The device should power off within a few seconds. If the device remains on, you may need to perform a manual shutdown."
|
||||||
|
msgstr "设备应在几秒钟内关闭。如果设备保持开启状态,您可能需要执行手动关机"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"admin/system/poweroffdevice": {
|
||||||
|
"title": "PowerOff",
|
||||||
|
"order": 99,
|
||||||
|
"action": {
|
||||||
|
"type": "view",
|
||||||
|
"path": "system/poweroffdevice"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"luci-app-poweroffdevice": {
|
||||||
|
"description": "Grant UCI access for luci-app-poweroffdevice",
|
||||||
|
"read": {
|
||||||
|
"ubus": {
|
||||||
|
"system": [ "info" ],
|
||||||
|
},
|
||||||
|
"file": {
|
||||||
|
"/sbin/poweroff": [ "exec" ],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"write": {
|
||||||
|
"file": {
|
||||||
|
"/sbin/poweroff": [ "exec" ]
|
||||||
|
},
|
||||||
|
"ubus": {
|
||||||
|
"file": [ "exec" ],
|
||||||
|
"system": [ "poweroff" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
16
package/diy/luci-app-temp-status/Makefile
Normal file
16
package/diy/luci-app-temp-status/Makefile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
LUCI_TITLE:=LuCI support for temperature status
|
||||||
|
LUCI_DESCRIPTION:=Show CPU/GPU/NPU temperature from thermal zones
|
||||||
|
LUCI_DEPENDS:=
|
||||||
|
LUCI_PKGARCH:=all
|
||||||
|
PKG_VERSION:=1
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
define Package/luci-app-temp-status/conffiles
|
||||||
|
endef
|
||||||
|
|
||||||
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|
||||||
|
# call BuildPackage - OpenWrt buildroot signature
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
'use strict';
|
||||||
|
'require view';
|
||||||
|
'require form';
|
||||||
|
'require poll';
|
||||||
|
'require fs';
|
||||||
|
'require ui';
|
||||||
|
|
||||||
|
function renderTempRow(zone, type, temp) {
|
||||||
|
var celsius = (temp / 1000).toFixed(1);
|
||||||
|
var color = '#4CAF50';
|
||||||
|
if (celsius > 75) color = '#FF9800';
|
||||||
|
if (celsius > 85) color = '#f44336';
|
||||||
|
|
||||||
|
return E('tr', { 'class': 'tr' }, [
|
||||||
|
E('td', { 'class': 'td left' }, [ type ]),
|
||||||
|
E('td', { 'class': 'td left' }, [ zone ]),
|
||||||
|
E('td', { 'class': 'td left', 'style': 'color:' + color + ';font-weight:bold' }, [ celsius + ' °C' ])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTempTable(zones) {
|
||||||
|
var table = E('table', { 'class': 'table' }, [
|
||||||
|
E('tr', { 'class': 'tr table-titles' }, [
|
||||||
|
E('th', { 'class': 'th' }, [ _('Type') ]),
|
||||||
|
E('th', { 'class': 'th' }, [ _('Zone') ]),
|
||||||
|
E('th', { 'class': 'th' }, [ _('Temperature') ])
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
var rows = zones.sort(function(a, b) {
|
||||||
|
return a.zone.localeCompare(b.zone);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
table.appendChild(renderTempRow(rows[i].zone, rows[i].type, rows[i].temp));
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
return view.extend({
|
||||||
|
load: function() {
|
||||||
|
return fs.list('/sys/class/thermal/').then(function(entries) {
|
||||||
|
var promises = [];
|
||||||
|
for (var i = 0; i < entries.length; i++) {
|
||||||
|
if (entries[i].name.indexOf('thermal_zone') === 0) {
|
||||||
|
promises.push(
|
||||||
|
fs.read('/sys/class/thermal/' + entries[i].name + '/type').then(function(zone, data) {
|
||||||
|
var type = data.trim();
|
||||||
|
return fs.read('/sys/class/thermal/' + zone + '/temp').then(function(temp) {
|
||||||
|
return { zone: zone, type: type, temp: parseInt(temp.trim()) };
|
||||||
|
});
|
||||||
|
}.bind(null, entries[i].name))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function(zones) {
|
||||||
|
var viewBody = E([], [
|
||||||
|
E('div', { 'class': 'cbi-section', 'id': 'temp-status' }, [
|
||||||
|
E('h3', { 'name': 'content' }, [ _('Temperature Status') ]),
|
||||||
|
E('div', { 'class': 'cbi-section-descr' }, [ _('Real-time temperature of CPU/GPU/NPU thermal zones on Rockchip RK3588.') ]),
|
||||||
|
renderTempTable(zones),
|
||||||
|
E('div', { 'style': 'margin-top:10px;color:#666;font-size:90%' }, [
|
||||||
|
_('Note: Temperatures above 75°C are shown in orange, above 85°C in red.')
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
poll.add(function() {
|
||||||
|
return fs.list('/sys/class/thermal/').then(function(entries) {
|
||||||
|
var promises = [];
|
||||||
|
for (var i = 0; i < entries.length; i++) {
|
||||||
|
if (entries[i].name.indexOf('thermal_zone') === 0) {
|
||||||
|
promises.push(
|
||||||
|
fs.read('/sys/class/thermal/' + entries[i].name + '/type').then(function(zone, data) {
|
||||||
|
var type = data.trim();
|
||||||
|
return fs.read('/sys/class/thermal/' + zone + '/temp').then(function(temp) {
|
||||||
|
return { zone: zone, type: type, temp: parseInt(temp.trim()) };
|
||||||
|
});
|
||||||
|
}.bind(null, entries[i].name))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}).then(function(updatedZones) {
|
||||||
|
var tableBody = viewBody.querySelector('#temp-status table');
|
||||||
|
if (tableBody) {
|
||||||
|
var newTable = renderTempTable(updatedZones);
|
||||||
|
tableBody.parentNode.replaceChild(newTable, tableBody);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 5);
|
||||||
|
|
||||||
|
return viewBody;
|
||||||
|
},
|
||||||
|
handleSaveApply: null,
|
||||||
|
handleSave: null,
|
||||||
|
handleReset: null
|
||||||
|
});
|
||||||
20
package/diy/luci-app-temp-status/po/zh-cn/tempstatus.po
Normal file
20
package/diy/luci-app-temp-status/po/zh-cn/tempstatus.po
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||||
|
|
||||||
|
msgid "Temperature Status"
|
||||||
|
msgstr "温度状态"
|
||||||
|
|
||||||
|
msgid "Real-time temperature of CPU/GPU/NPU thermal zones on Rockchip RK3588."
|
||||||
|
msgstr "Rockchip RK3588 CPU/GPU/NPU 温度实时监控"
|
||||||
|
|
||||||
|
msgid "Type"
|
||||||
|
msgstr "类型"
|
||||||
|
|
||||||
|
msgid "Zone"
|
||||||
|
msgstr "区域"
|
||||||
|
|
||||||
|
msgid "Temperature"
|
||||||
|
msgstr "温度"
|
||||||
|
|
||||||
|
msgid "Note: Temperatures above 75°C are shown in orange, above 85°C in red."
|
||||||
|
msgstr "注:75°C 以上显示橙色,85°C 以上显示红色"
|
||||||
20
package/diy/luci-app-temp-status/po/zh_Hans/tempstatus.po
Normal file
20
package/diy/luci-app-temp-status/po/zh_Hans/tempstatus.po
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||||
|
|
||||||
|
msgid "Temperature Status"
|
||||||
|
msgstr "温度状态"
|
||||||
|
|
||||||
|
msgid "Real-time temperature of CPU/GPU/NPU thermal zones on Rockchip RK3588."
|
||||||
|
msgstr "Rockchip RK3588 CPU/GPU/NPU 温度实时监控"
|
||||||
|
|
||||||
|
msgid "Type"
|
||||||
|
msgstr "类型"
|
||||||
|
|
||||||
|
msgid "Zone"
|
||||||
|
msgstr "区域"
|
||||||
|
|
||||||
|
msgid "Temperature"
|
||||||
|
msgstr "温度"
|
||||||
|
|
||||||
|
msgid "Note: Temperatures above 75°C are shown in orange, above 85°C in red."
|
||||||
|
msgstr "注:75°C 以上显示橙色,85°C 以上显示红色"
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"admin/status/tempstatus": {
|
||||||
|
"title": "Temperature",
|
||||||
|
"order": 90,
|
||||||
|
"action": {
|
||||||
|
"type": "view",
|
||||||
|
"path": "system/tempstatus"
|
||||||
|
},
|
||||||
|
"depends": {
|
||||||
|
"acl": [ "luci-app-temp-status" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"luci-app-temp-status": {
|
||||||
|
"description": "Grant access to temperature status",
|
||||||
|
"read": {
|
||||||
|
"file": {
|
||||||
|
"/sys/class/thermal/": [ "list" ],
|
||||||
|
"/sys/class/thermal/*/type": [ "read" ],
|
||||||
|
"/sys/class/thermal/*/temp": [ "read" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
48
package/diy/zram-swap/Makefile
Normal file
48
package/diy/zram-swap/Makefile
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013-2021 OpenWrt.org
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=zram-swap
|
||||||
|
PKG_RELEASE:=32
|
||||||
|
|
||||||
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define Package/zram-swap
|
||||||
|
SECTION:=utils
|
||||||
|
CATEGORY:=Base system
|
||||||
|
DEPENDS:= \
|
||||||
|
+@BUSYBOX_CONFIG_FEATURE_SWAPON_DISCARD \
|
||||||
|
+@BUSYBOX_CONFIG_FEATURE_SWAPON_PRI \
|
||||||
|
+@BUSYBOX_CONFIG_MKSWAP \
|
||||||
|
+@BUSYBOX_CONFIG_SWAPOFF \
|
||||||
|
+@BUSYBOX_CONFIG_SWAPON \
|
||||||
|
+kmod-zram
|
||||||
|
TITLE:=ZRAM swap scripts
|
||||||
|
PKGARCH:=all
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/zram-swap/description
|
||||||
|
A script to activate swaping on a compressed zram partition. This
|
||||||
|
could be used to increase the available memory, by using compressed
|
||||||
|
memory.
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Prepare
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Configure
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Compile
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/zram-swap/install
|
||||||
|
$(INSTALL_DIR) $(1)/etc/init.d
|
||||||
|
$(INSTALL_BIN) ./files/zram.init $(1)/etc/init.d/zram
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,zram-swap))
|
||||||
190
package/diy/zram-swap/files/zram.init
Executable file
190
package/diy/zram-swap/files/zram.init
Executable file
@ -0,0 +1,190 @@
|
|||||||
|
#!/bin/sh /etc/rc.common
|
||||||
|
|
||||||
|
START=15
|
||||||
|
|
||||||
|
extra_command "compact" "Trigger compaction for all zram swap devices"
|
||||||
|
extra_command "status" "Print out information & statistics about zram swap devices"
|
||||||
|
|
||||||
|
ram_getsize()
|
||||||
|
{
|
||||||
|
local line
|
||||||
|
|
||||||
|
while read line; do case "$line" in MemTotal:*) set $line; echo "$2"; break ;; esac; done </proc/meminfo
|
||||||
|
}
|
||||||
|
|
||||||
|
zram_getsize() # in megabytes
|
||||||
|
{
|
||||||
|
local zram_size="$( uci -q get system.@system[0].zram_size_mb )"
|
||||||
|
local ram_size="$( ram_getsize )"
|
||||||
|
|
||||||
|
if [ -z "$zram_size" ]; then
|
||||||
|
# e.g. 6mb for 16mb-routers or 61mb for 128mb-routers
|
||||||
|
echo $(( ram_size / 2048 ))
|
||||||
|
else
|
||||||
|
echo "$zram_size"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
zram_dev()
|
||||||
|
{
|
||||||
|
local idx="$1"
|
||||||
|
echo "/dev/zram${idx:-0}"
|
||||||
|
}
|
||||||
|
|
||||||
|
zram_reset()
|
||||||
|
{
|
||||||
|
local dev="$1"
|
||||||
|
local message="$2"
|
||||||
|
local proc_entry="/sys/block/$( basename "$dev" )/reset"
|
||||||
|
|
||||||
|
logger -s -t zram_reset -p daemon.debug "$message via $proc_entry"
|
||||||
|
echo "1" >"$proc_entry"
|
||||||
|
}
|
||||||
|
|
||||||
|
zram_getdev()
|
||||||
|
{
|
||||||
|
#get unallocated zram dev
|
||||||
|
local zdev=$( zram_dev )
|
||||||
|
|
||||||
|
if [ "$(mount | grep $zdev)" ]; then
|
||||||
|
local idx=$(cat /sys/class/zram-control/hot_add)
|
||||||
|
zdev="$( zram_dev $idx )"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $zdev
|
||||||
|
}
|
||||||
|
|
||||||
|
zram_comp_algo()
|
||||||
|
{
|
||||||
|
local dev="$1"
|
||||||
|
local zram_comp_algo="$( uci -q get system.@system[0].zram_comp_algo )"
|
||||||
|
|
||||||
|
if [ -z "$zram_comp_algo" ]; then
|
||||||
|
# default to lzo, which is always available
|
||||||
|
zram_comp_algo="lzo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $(grep -c "$zram_comp_algo" /sys/block/$( basename $dev )/comp_algorithm) -ne 0 ]; then
|
||||||
|
logger -s -t zram_comp_algo -p daemon.debug "set compression algorithm '$zram_comp_algo' for zram '$dev'"
|
||||||
|
echo $zram_comp_algo > "/sys/block/$( basename $dev )/comp_algorithm"
|
||||||
|
else
|
||||||
|
logger -s -t zram_comp_algo -p daemon.debug "compression algorithm '$zram_comp_algo' is not supported for '$dev'"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#print various stats info about zram swap device
|
||||||
|
zram_stats()
|
||||||
|
{
|
||||||
|
local zdev="/sys/block/$( basename "$1" )"
|
||||||
|
|
||||||
|
printf "\nGathering stats info for zram device \"$( basename "$1" )\"\n\n"
|
||||||
|
|
||||||
|
printf "ZRAM\n----\n"
|
||||||
|
printf "%-25s - %s\n" "Block device" $zdev
|
||||||
|
awk '{ printf "%-25s - %d MiB\n", "Device size", $1/1024/1024 }' <$zdev/disksize
|
||||||
|
printf "%-25s - %s\n" "Compression algo" "$(cat $zdev/comp_algorithm)"
|
||||||
|
|
||||||
|
awk 'BEGIN { fmt = "%-25s - %.2f %s\n"
|
||||||
|
fmt2 = "%-25s - %d\n"
|
||||||
|
print "\nDATA\n----" }
|
||||||
|
{ printf fmt, "Original data size", $1/1024/1024, "MiB"
|
||||||
|
printf fmt, "Compressed data size", $2/1024/1024, "MiB"
|
||||||
|
printf fmt, "Compress ratio", $1/$2, ""
|
||||||
|
print "\nMEMORY\n------"
|
||||||
|
printf fmt, "Memory used, total", $3/1024/1024, "MiB"
|
||||||
|
printf fmt, "Allocator overhead", ($3-$2)/1024/1024, "MiB"
|
||||||
|
printf fmt, "Allocator efficiency", $2/$3*100, "%"
|
||||||
|
printf fmt, "Maximum memory ever used", $5/1024/1024, "MiB"
|
||||||
|
printf fmt, "Memory limit", $4/1024/1024, "MiB"
|
||||||
|
print "\nPAGES\n-----"
|
||||||
|
printf fmt2, "Same pages count", $6
|
||||||
|
printf fmt2, "Pages compacted", $7 }' <$zdev/mm_stat
|
||||||
|
|
||||||
|
awk '{ printf "%-25s - %d\n", "Free pages discarded", $4 }' <$zdev/io_stat
|
||||||
|
}
|
||||||
|
|
||||||
|
zram_compact()
|
||||||
|
{
|
||||||
|
# compact zram device (reduce memory allocation overhead)
|
||||||
|
local zdev="/sys/block/$( basename "$1" )"
|
||||||
|
|
||||||
|
local old_mem_used=$(awk '{print $3}' <$zdev/mm_stat)
|
||||||
|
local old_overhead=$(awk '{print $3-$2}' <$zdev/mm_stat)
|
||||||
|
|
||||||
|
echo 1 > $zdev/compact
|
||||||
|
|
||||||
|
# If not running interactively, than just return
|
||||||
|
[ -z "$PS1" ] && return 0
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Compacting zram device $zdev"
|
||||||
|
awk -v old_mem="$old_mem_used" -v ovr="$old_overhead" 'BEGIN { fmt = "%-25s - %.1f %s\n" }
|
||||||
|
{ printf fmt, "Memory usage reduced by ", (old_mem-$3)/1024/1024, "MiB"
|
||||||
|
printf fmt, "Overhead reduced by", (ovr-($3-$2))/ovr*100, "%" }' <$zdev/mm_stat
|
||||||
|
}
|
||||||
|
|
||||||
|
start()
|
||||||
|
{
|
||||||
|
[ -e /proc/swaps ] || {
|
||||||
|
logger -s -t zram_start -p daemon.crit "kernel doesn't support swap"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $( grep -cs zram /proc/swaps ) -ne 0 ]; then
|
||||||
|
logger -s -t zram_start -p daemon.notice "zram swap is already mounted"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local zram_dev="$( zram_getdev )"
|
||||||
|
|
||||||
|
[ -e "$zram_dev" ] || {
|
||||||
|
logger -s -t zram_start -p daemon.crit "[ERROR] device '$zram_dev' not found"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
local zram_size="$( zram_getsize )"
|
||||||
|
local zram_priority="$( uci -q get system.@system[0].zram_priority )"
|
||||||
|
|
||||||
|
if [ -z "$zram_priority" ]; then
|
||||||
|
zram_priority="100"
|
||||||
|
fi
|
||||||
|
|
||||||
|
logger -s -t zram_start -p daemon.debug "activating '$zram_dev' for swapping ($zram_size MiB)"
|
||||||
|
|
||||||
|
zram_reset "$zram_dev" "enforcing defaults"
|
||||||
|
zram_comp_algo "$zram_dev"
|
||||||
|
echo $(( $zram_size * 1024 * 1024 )) >"/sys/block/$( basename "$zram_dev" )/disksize"
|
||||||
|
busybox mkswap "$zram_dev"
|
||||||
|
busybox swapon -d -p $zram_priority "$zram_dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop()
|
||||||
|
{
|
||||||
|
local zram_dev
|
||||||
|
|
||||||
|
for zram_dev in $( grep zram /proc/swaps |awk '{print $1}' ); do {
|
||||||
|
logger -s -t zram_stop -p daemon.debug "deactivate swap $zram_dev"
|
||||||
|
busybox swapoff "$zram_dev" && zram_reset "$zram_dev" "claiming memory back"
|
||||||
|
local dev_index="$( echo $zram_dev | grep -o "[0-9]*$" )"
|
||||||
|
if [ $dev_index -ne 0 ]; then
|
||||||
|
logger -s -t zram_stop -p daemon.debug "removing zram $zram_dev"
|
||||||
|
echo $dev_index > /sys/class/zram-control/hot_remove
|
||||||
|
fi
|
||||||
|
} done
|
||||||
|
}
|
||||||
|
|
||||||
|
# show memory stats for all zram swaps
|
||||||
|
status()
|
||||||
|
{
|
||||||
|
for zram_dev in $( grep zram /proc/swaps |awk '{print $1}' ); do {
|
||||||
|
zram_stats "$zram_dev"
|
||||||
|
} done
|
||||||
|
}
|
||||||
|
|
||||||
|
# trigger compaction for all zram swaps
|
||||||
|
compact()
|
||||||
|
{
|
||||||
|
for zram_dev in $( grep zram /proc/swaps |awk '{print $1}' ); do {
|
||||||
|
zram_compact "$zram_dev"
|
||||||
|
} done
|
||||||
|
}
|
||||||
@ -196,6 +196,8 @@ CONFIG_PACKAGE_luci-app-nlbwmon=y
|
|||||||
CONFIG_PACKAGE_luci-app-vnstat=y
|
CONFIG_PACKAGE_luci-app-vnstat=y
|
||||||
CONFIG_PACKAGE_luci-app-diag-core=y
|
CONFIG_PACKAGE_luci-app-diag-core=y
|
||||||
CONFIG_PACKAGE_luci-app-watchcat=y
|
CONFIG_PACKAGE_luci-app-watchcat=y
|
||||||
|
CONFIG_PACKAGE_luci-app-poweroffdevice=y
|
||||||
|
CONFIG_PACKAGE_luci-app-temp-status=y
|
||||||
|
|
||||||
# Chinese i18n for network monitoring
|
# Chinese i18n for network monitoring
|
||||||
CONFIG_PACKAGE_luci-i18n-statistics-zh-cn=y
|
CONFIG_PACKAGE_luci-i18n-statistics-zh-cn=y
|
||||||
@ -233,3 +235,4 @@ CONFIG_PACKAGE_iperf3=y
|
|||||||
CONFIG_PACKAGE_jq=y
|
CONFIG_PACKAGE_jq=y
|
||||||
CONFIG_PACKAGE_curl=y
|
CONFIG_PACKAGE_curl=y
|
||||||
CONFIG_PACKAGE_bind-dig=y
|
CONFIG_PACKAGE_bind-dig=y
|
||||||
|
CONFIG_PACKAGE_zram-swap=y
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user