🌴 Sync 2026-03-05 23:51:42

This commit is contained in:
github-actions[bot] committed 2026-03-05 23:51:42 +08:00
1 parent 97c049ed0a
commit 0acff03804
14253 files changed
+3893239

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
# Copyright (C) 2019 Openwrt.org
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI disk monitor
LUCI_DEPENDS:=+smartmontools
LUCI_PKGARCH:=all
PKG_MAINTAINER:=animefansxj <af_xj@hotmail.cn>
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
@@ -0,0 +1,132 @@
--[[
LuCI - Lua Configuration Interface - smartctl support
Script by animefans_xj @ nvacg.org (af_xj@hotmail.com , xujun@smm.cn)
Licensed under the GNU GPL License, Version 3 (the "license");
you may not use this file except in compliance with the License.
you may obtain a copy of the License at
http://www.gnu.org/licenses/gpl.txt
$Id$
]]--
module("luci.controller.smartinfo",package.seeall)
function index()
require("luci.i18n")
luci.i18n.loadc("smartinfo")
if not nixio.fs.access("/etc/config/smartinfo") then
return
end
local page = entry({"admin","nas","smartinfo"},cbi("smartinfo"),_("S.M.A.R.T Info"))
page.i18n="smartinfo"
page.dependent=true
entry({"admin","nas","smartinfo","smartdetail"},call("smart_detail")).leaf = true
entry({"admin","nas","smartinfo","status"}, call("smart_status")).leaf = true
entry({"admin","nas","smartinfo","run"},call("run_smart")).leaf=true
entry({"admin","nas","smartinfo","smartattr"},call("smart_attr")).leaf=true
end
function smart_status()
local cmd = io.popen("/usr/lib/smartinfo/smart_status.sh")
if cmd then
local dev = { }
while true do
local ln = cmd:read("*l")
if not ln then
break
elseif ln:match("^/%l+/%l+:%a+") then
local name,status = ln:match("^/%l+/(%l+):(%a+)")
local model,size
if (status=="OK" or status=="Failed" or status=="Unsupported") then
model="%s %s" % {nixio.fs.readfile("/sys/class/block/%s/device/vendor" % name), nixio.fs.readfile("/sys/class/block/%s/device/model" % name)}
local s = tonumber((nixio.fs.readfile("/sys/class/block/%s/size" % name)))
size = "%s MB" % {s and math.floor(s / 2048)}
else
model="Unavailabled"
size="Unavailabled"
end
if name and status then
dev[#dev+1]= {
name = name,
model = model,
size = size,
status = status
}
end
else
end
end
cmd:close()
luci.http.prepare_content("application/json")
luci.http.write_json(dev)
end
end
function run_smart(dev)
local cmd = io.popen("smartctl --attributes -d sat /dev/%s" % dev)
if cmd then
local report = {}
local ln = cmd:read("*all")
report = {
out = ln
}
cmd:close()
luci.http.prepare_content("application/json")
luci.http.write_json(report)
end
end
function smart_detail(dev)
luci.template.render("smartinfo/smart_detail", {dev=dev})
end
function smart_attr(dev)
local cmd = io.popen("smartctl --attributes -d sat /dev/%s" % dev)
if cmd then
local attr = { }
while true do
local ln = cmd:read("*l")
if not ln then
break
elseif ln:match("^.*%d+%s+.+%s+.+%s+.+%s+.+%s+.+%s+.+%s+.+%s+.+%s+.+") then
local id,attrbute,flag,value,worst,thresh,type,updated,raw = ln:match("^%s*(%d+)%s+([%a%p]+)%s+(%w+)%s+(%d+)%s+(%d+)%s+(%d+)%s+([%a%p]+)%s+(%a+)%s+[%w%p]+%s+(.+)")
id= "%x" % id
if not id:match("^%w%w") then
id = "0%s" % id
end
attr[#attr+1]= {
id = id:upper(),
attrbute = attrbute,
flag = flag,
value = value,
worst = worst,
thresh = thresh,
type = type,
updated = updated,
raw = raw
}
else
end
end
cmd:close()
luci.http.prepare_content("application/json")
luci.http.write_json(attr)
end
end
@@ -0,0 +1,85 @@
--[[
LuCI - Lua Configuration Interface - smartctl support
Script by animefans_xj @ nvacg.org (af_xj@hotmail.com , xujun@smm.cn)
Licensed under the GNU GPL License, Version 3 (the "license");
you may not use this file except in compliance with the License.
you may obtain a copy of the License at
http://www.gnu.org/licenses/gpl.txt
$Id$
]]--
require("luci.sys")
require("luci.util")
m=Map("smartinfo",translate("S.M.A.R.T Info"),translate("This widget allow you to monitor your storage devices which support S.M.A.R.T technology."))
s=m:section(TypedSection,"smartinfo",translate("S.M.A.R.T Report Settings"))
s.addremove=false
s.anonymous=true
m:section(SimpleSection).template="smartinfo/smart_status"
s:tab("general",translate("Global"))
--s:tab("detail",translate("Detail"))
enable=s:taboption("general", Flag, "enabled", translate("Enabled"))
enable.rmempty=false
enable.default = 0
function enable.cfgvalue(self,section)
return luci.sys.init.enabled("smartinfo") and self.enabled or self.disabled
end
function enable.write(self,section,value)
if value == "1" then
luci.sys.call("/etc/init.d/smartinfo stop > /dev/null")
luci.sys.call("/etc/init.d/smartinfo enable > /dev/null")
luci.sys.call("/etc/init.d/smartinfo start > /dev/null")
else
luci.sys.call("/etc/init.d/smartinfo stop > /dev/null")
luci.sys.call("/etc/init.d/smartinfo disable > /dev/null")
end
end
check_interval=s:taboption("general",Value,"time_step",translate("Check Interval"))
check_interval.rmempty=false
check_interval.placeholder="1"
check_interval.datatype="range(1,60)"
check_interval.template="smartinfo/detail_begin_value"
time_unit=s:taboption("general",ListValue,"time_unit",translate("Unit"))
time_unit.rmempty=false
time_unit.template="smartinfo/detail_end_listvalue"
time_unit:value("minute",translate("Minutes"))
time_unit:value("hour",translate("Hours"))
time_unit:value("day",translate("Days"))
time_unit:value("week",translate("Weeks"))
log_enable=s:taboption("general",Flag,"log_enabled",translate("Log to file"))
log_enable.template="smartinfo/detail_begin_flag"
log_enable.rmempty=false
log_path=s:taboption("general",Value,"log_path",translate("at"))
log_path.template="smartinfo/detail_end_value"
log_path.placeholder="/tmp/log"
log_path.rmempty=false
touch_enable=s:taboption("general",Flag,"touch_enabled",translate("Touch a warning file when disk fail"))
touch_enable.template="smartinfo/detail_begin_flag"
touch_enable.rmempty=false
touch_path=s:taboption("general",Value,"touch_path",translate("at"))
touch_path.template="smartinfo/detail_end_value"
touch_path.placeholder="/tmp"
touch_path.rmempty=false
devices=s:taboption("general",DynamicList,"device",translate("Devices to monitor"))
local device_name = nil
local device_model = nil
for d in nixio.fs.glob("/dev/sd?") do
device_name=nixio.fs.basename(d)
device_model="%s %s" % {nixio.fs.readfile("/sys/class/block/%s/device/vendor" % device_name), nixio.fs.readfile("/sys/class/block/%s/device/model" % device_name)}
devices:value(d, "%s: %s" % {device_name, device_model})
end
return m
@@ -0,0 +1 @@
<%+smartinfo/smart_status%>
@@ -0,0 +1,10 @@
<!-- Org doc from luci-app-ddns -->
<input type="hidden" value="1"<%=
attr("name", "cbi.cbe." .. self.config .. "." .. section .. "." .. self.option)
%> />
<%+cbi/valueheader%>
<input class="cbi-input-checkbox" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)" type="checkbox" <%=
attr("id", cbid) .. attr("name", cbid) .. attr("value", self.enabled or 1) ..
ifattr((self:cfgvalue(section) or self.default) == self.enabled, "checked", "checked")
%> />
@@ -0,0 +1,7 @@
<!-- Org doc from luci-app-ddns -->
<%+cbi/valueheader%>
<input type="text" class="cbi-input-text" style="width: 9em;" onchange="cbi_d_update(this.id)"<%=
attr("name", cbid) .. attr("id", cbid) .. attr("value", self:cfgvalue(section) or self.default) ..
ifattr(self.size, "size") .. ifattr(self.placeholder, "placeholder")
%> />
@@ -0,0 +1,20 @@
<!-- Org doc from luci-app-ddns -->
&#160;
<% if self.widget == "select" then %>
<select class="cbi-input-select" style="width: 10em;" onchange="cbi_d_update(this.id)"<%= attr("id", cbid) .. attr("name", cbid) .. ifattr(self.size, "size") %>>
<% for i, key in pairs(self.keylist) do -%>
<option id="cbi-<%=self.config.."-"..section.."-"..self.option.."-"..key%>"<%= attr("value", key) .. ifattr(tostring(self:cfgvalue(section) or self.default) == key, "selected", "selected") %>><%=striptags(self.vallist[i])%></option>
<%- end %>
</select>
<% elseif self.widget == "radio" then
local c = 0
for i, key in pairs(self.keylist) do
c = c + 1
%>
<input class="cbi-input-radio" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)" type="radio"<%= attr("id", cbid..c) .. attr("name", cbid) .. attr("value", key) .. ifattr((self:cfgvalue(section) or self.default) == key, "checked", "checked") %> />
<label<%= attr("for", cbid..c) %>><%=self.vallist[i]%></label>
<% if c == self.size then c = 0 %><% if self.orientation == "horizontal" then %>&#160;<% else %><br /><% end %>
<% end end %>
<% end %>
<%+cbi/valuefooter%>
@@ -0,0 +1,9 @@
<!-- Org doc from luci-app-ddns -->
&#160;&#160;
<%= self.title %>
<input type="text" class="cbi-input-text" style="width: 17em;" onchange="cbi_d_update(this.id)"<%=
attr("name", cbid) .. attr("id", cbid) .. attr("value", self:cfgvalue(section) or self.default) ..
ifattr(self.size, "size") .. ifattr(self.placeholder, "placeholder")
%> />
<%+cbi/valuefooter%>
@@ -0,0 +1,82 @@
<html>
<head>
<title>S.M.A.R.T detail of <%=dev%></title>
<link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" />
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
<script type="text/javascript">//<![CDATA[
XHR.get('<%=luci.dispatcher.build_url("admin", "nas", "smartinfo", "smartattr", dev)%>', null,
function(x, st)
{
var tb = document.getElementById('smart_attr_table');
if (st && tb)
{
/* clear all rows */
while( tb.rows.length > 1 )
tb.deleteRow(1);
for( var i = 0; i < st.length; i++ )
{
var tr = tb.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
var td = null
tr.insertCell(-1).innerHTML = st[i].id;
tr.insertCell(-1).innerHTML = st[i].attrbute;
tr.insertCell(-1).innerHTML = st[i].flag;
tr.insertCell(-1).innerHTML = st[i].value;
tr.insertCell(-1).innerHTML = st[i].worst;
tr.insertCell(-1).innerHTML = st[i].thresh;
tr.insertCell(-1).innerHTML = st[i].type;
tr.insertCell(-1).innerHTML = st[i].updated;
tr.insertCell(-1).innerHTML = st[i].raw;
if( ( st[i].id == '05' || st[i].id == 'C5' ) && st[i].raw != '0' )
{
tr.style.cssText = "background-color:red !important;";
}
}
if( tb.rows.length == 1 )
{
var tr = tb.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 4;
td.innerHTML = '<em><br /><%:No Attrbute to display.%></em>';
}
}
}
);
//]]></script>
</head>
<body>
<div id="maincontainer">
<div id="maincontent">
<fieldset class="cbi-section">
<legend><%:S.M.A.R.T Attrbutes%>: /dev/<%=dev%></legend>
<table class="cbi-section-table" id="smart_attr_table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:ID%></th>
<th class="cbi-section-table-cell"><%:Attrbute%></th>
<th class="cbi-section-table-cell"><%:Flag%></th>
<th class="cbi-section-table-cell"><%:Value%></th>
<th class="cbi-section-table-cell"><%:Worst%></th>
<th class="cbi-section-table-cell"><%:Thresh%></th>
<th class="cbi-section-table-cell"><%:Type%></th>
<th class="cbi-section-table-cell"><%:Updated%></th>
<th class="cbi-section-table-cell"><%:Raw%></th>
</tr>
<tr class="cbi-section-table-row">
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
</fieldset>
</div>
</div>
</body>
</html>
@@ -0,0 +1,80 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "nas", "smartinfo", "status")%>', null,
function(x, st)
{
var tb = document.getElementById('smart_status_table');
if (st && tb)
{
/* clear all rows */
while( tb.rows.length > 1 )
tb.deleteRow(1);
for( var i = 0; i < st.length; i++ )
{
var tr = tb.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
var td = null
tr.insertCell(-1).innerHTML = st[i].name;
tr.insertCell(-1).innerHTML = st[i].model;
tr.insertCell(-1).innerHTML = st[i].size;
if(st[i].status == 'Failed')
{
td = tr.insertCell(-1);
td.innerHTML = "<font color='black'>" + st[i].status + "</font>"
td.style.cssText = "background-color:red !important;";
}
else
{
tr.insertCell(-1).innerHTML = st[i].status;
}
if(st[i].status == 'Failed' || st[i].status == 'OK')
{
td = tr.insertCell(-1);
td.innerHTML = "<input class='cbi-button cbi-button-find' type='button' value=' <%:Show%> ' onclick='show_detail(\"" + st[i].name + "\");' />"
}
else
{
tr.insertCell(-1).innerHTML = "---";
}
}
if( tb.rows.length == 1 )
{
var tr = tb.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 4;
td.innerHTML = '<em><br /><%:No storage device to monitor.%></em>';
}
}
}
);
//]]></script>
<script type="text/javascript">
function show_detail(dev)
{
window.open('<%=luci.dispatcher.build_url("admin", "nas", "smartinfo", "smartdetail")%>/' + dev,
'newwindow','height=480,width=800,top=100,left=200,toolbar=no,menubar=no,scrollbars=yes, resizable=no,location=no, status=no')
}
</script>
<fieldset class="cbi-section">
<legend><%:S.M.A.R.T Status%></legend>
<table class="cbi-section-table" id="smart_status_table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Device%></th>
<th class="cbi-section-table-cell"><%:Model%></th>
<th class="cbi-section-table-cell"><%:Size%></th>
<th class="cbi-section-table-cell"><%:Status%></th>
<th class="cbi-section-table-cell"><%:Detail%></th>
</tr>
<tr class="cbi-section-table-row">
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
</fieldset>
+116
View File
@@ -0,0 +1,116 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-02-12 20:45+0800\n"
"PO-Revision-Date: 2016-02-16 21:20+0800\n"
"Last-Translator: 穿越蓝天 < admin@nvacg.com , af_xj@hotmail.com >\n"
"Language: cn\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 1.5.4\n"
"Project-Id-Version: \n"
"Language-Team: \n"
msgid "S.M.A.R.T Info"
msgstr "磁盘监控"
msgid "This widget allow you to monitor your storage devices which support S.M.A.R.T technology."
msgstr "该工具帮助您通过S.M.A.R.T技术来监控您硬盘的健康状况."
msgid "S.M.A.R.T Report Settings"
msgstr "S.M.A.R.T 报告设置"
msgid "Enabled"
msgstr "启用"
msgid "Check Interval"
msgstr "检查间隔"
msgid "Unit"
msgstr "单位"
msgid "Minutes"
msgstr "分"
msgid "Hours"
msgstr "小时"
msgid "Days"
msgstr "天"
msgid "Weeks"
msgstr "周"
msgid "Log to file"
msgstr "记录到文件"
msgid "at"
msgstr "位于"
msgid "Touch a warning file when disk fail"
msgstr "故障时生成示警文件"
msgid "Devices to monitor"
msgstr "监控这些设备"
msgid "S.M.A.R.T Status"
msgstr "S.M.A.R.T 状况"
msgid "Device"
msgstr "设备"
msgid "Model"
msgstr "型号"
msgid "Size"
msgstr "大小"
msgid "Status"
msgstr "状况"
msgid "Collecting data..."
msgstr "正在收集数据"
msgid "Detail"
msgstr "详细"
msgid "Show"
msgstr "查看"
msgid "Global"
msgstr "全局"
msgid "No Attrbute to display."
msgstr "没有可显示的属性"
msgid "S.M.A.R.T Attrbutes"
msgstr "S.M.A.R.T 属性"
msgid "ID"
msgstr "ID"
msgid "Attrbute"
msgstr "属性名称"
msgid "Flag"
msgstr "标记"
msgid "Value"
msgstr "值"
msgid "Worst"
msgstr "最坏"
msgid "Thresh"
msgstr "临界值"
msgid "Type"
msgstr "类型"
msgid "Updated"
msgstr "更新"
msgid "Raw"
msgstr "原始值"
+1
View File
@@ -0,0 +1 @@
zh-cn
@@ -0,0 +1,11 @@
config smartinfo 'main'
option enabled '1'
list device '/dev/sda'
option log_enabled '1'
option log_path '/tmp/DiskLog'
option time_unit 'day'
option time_step '1'
option touch_enabled '1'
option touch_path '/tmp'
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh /etc/rc.common
START=95
boot() {
return 0
}
start() {
/usr/lib/smartinfo/smart_checker.sh > /dev/null 2>&1 &
}
stop() {
killall -9 smart_checker.sh
}
@@ -0,0 +1,115 @@
#!/bin/sh
# Copyright (C) 2016 NVACG , 穿越蓝天/animefans_xj
# af_xj@hotmail.com
#
#Licensed under the GNU GPL License, Version 3 (the "license");
#you may not use this file except in compliance with the License.
#you may obtain a copy of the License at
#
# http://www.gnu.org/licenses/gpl.txt
. /lib/functions.sh
. /usr/lib/smartinfo/smart_functions.sh
config_load "smartinfo"
init() {
local enable time time_step time_unit log_enabled log_path touch_enable touch_path
}
config_get enabled main enabled
config_get time_step main time_step
config_get time_unit main time_unit
config_get log_enabled main log_enabled
config_get log_path main log_path
config_get touch_enabled main touch_enabled
config_get touch_path main touch_path
echo "SMART CHECK SCRIPT"
echo "Paramter ==================="
echo "Enabled: $enabled"
echo "Time Step: $time_step"
echo "Time Unit: $time_unit"
echo "Log: $log_enabled"
echo "Log ath: $log_path"
echo "Warn: $touch_enabled"
echo "Warn Path: $touch_path"
if [ $enabled -ne 1 ]; then
exit 0
fi
# 根据选定的时间间隔生成秒数
case $time_unit in
"minute")
let time=time_step*60
;;
"hour")
let time=time_step*3600
;;
"day")
let time=time_step*86400
;;
"week")
let time=time_step*604800
;;
*)
let time=time_step*60
;;
esac
echo "Calculated Time: $time"
echo ""
main_process() {
do_smart_check $1
local RETVAL=$?
local Device=`echo $1 |awk -F/ '{print $NF}'`
local Model
# 如果指定的磁盘在线则获取型号
[ -d /sys/class/block/$Device ] && Model=`cat /sys/class/block/$Device/device/vendor``cat /sys/class/block/$Device/device/model`
# 如果路径不存在则创建目录
[ $log_enabled ] && ! [ -d $log_path ] && mkdir -p $log_path
[ $touch_enabled ] && ! [ -d $touch_path ] && mkdir -p $touch_path
case $RETVAL in
0)
# 设备健康
[ $log_enabled ] && [ -d $log_path ] && echo `date '+%Y-%m-%d %H:%M'`" [$Model]: Passed Disk Check." >> $log_path/smartinfo_$Device.log
[ -f $touch_path/$Device-DiskDamaged ] && rm $touch_path/$Device-DiskDamaged
;;
1)
# 设备故障
logger -p daemon.warn -t smartinfo "Device $1 S.M.A.R.T status Failed!"
[ $log_enabled ] && [ -d $log_path ] && echo `date '+%Y-%m-%d %H:%M'`" [$Model]: Disk Damaged." >> $log_path/smartinfo_$Device.log
[ $touch_enabled ] && [ -d $touch_path ] && touch $touch_path/$Device-DiskDamaged
;;
2)
# 设备离线
logger -p daemon.warn -t smartinfo "Device $1 Offline."
[ $log_enabled ] && [ -d $log_path ] && echo `date '+%Y-%m-%d %H:%M'`" : Disk Offline." >> $log_path/smartinfo_$Device.log
[ -f $touch_path/$Device-DiskDamaged ] && rm $touch_path/$Device-DiskDamaged
;;
3)
# 不支持S.M.A.R.T
[ $log_enabled ] && [ -d $log_path ] && echo `date '+%Y-%m-%d %H:%M'`" [$Model]: Unsupport S.M.A.R.T." >> $log_path/smartinfo_$Device.log
[ -f $touch_path/$Device-DiskDamaged ] && rm $touch_path/$Device-DiskDamaged
;;
*)
;;
esac
}
while [ true ]
do
echo `date '+%Y-%m-%d %H:%M'`" Execute the S.M.A.R.T Check."
# 执行S.M.A.R.T检测
config_list_foreach main device main_process
# 循环延迟
sleep $time
done
@@ -0,0 +1,56 @@
#!/bin/sh
# Copyright (C) 2016 NVACG , 穿越蓝天/animefans_xj
# af_xj@hotmail.com
#
#Licensed under the GNU GPL License, Version 3 (the "license");
#you may not use this file except in compliance with the License.
#you may obtain a copy of the License at
#
# http://www.gnu.org/licenses/gpl.txt
do_smart_check() {
# 看看指定的设备是否在线
if [ -b $1 ]; then
# 如果在线,看看是否支持S.M.A.R.T。支持,则对其执行SMART检测,判断输出是否包含PASSED
result=`/usr/sbin/smartctl -d sat -H $1`
if [ $? -eq "2" ]; then
# 不支持S.M.A.R.T
return 3
fi
result=`echo $result | grep -c PASSED`
if [ $result -ne 0 ]; then
#无故障
return 0
else
#故障
return 1
fi
else
# 设备离线
return "2"
fi
}
do_simple_smart_check() {
# 看看指定的设备是否在线
if [ -b $1 ]; then
# 如果在线,则对其执行SMART检测,判断输出是否包含PASSED
result=`/usr/sbin/smartctl -d sat -H $1`
if [ $? -eq "2" ]; then
# 不支持S.M.A.R.T
echo "$1:Unsupported"
exit 0
fi
result=`echo $result | grep -c PASSED`
if [ $result -ne 0 ]; then
echo "$1:OK"
else
echo "$1:Failed"
fi
else
# 如果不在线则输出设备离线
echo "$1:Offline"
fi
}
@@ -0,0 +1,17 @@
#!/bin/sh
# Copyright (C) 2016 NVACG , 穿越蓝天/animefans_xj
# af_xj@hotmail.com
#
#Licensed under the GNU GPL License, Version 3 (the "license");
#you may not use this file except in compliance with the License.
#you may obtain a copy of the License at
#
# http://www.gnu.org/licenses/gpl.txt
. /lib/functions.sh
. /usr/lib/smartinfo/smart_functions.sh
config_load "smartinfo"
# 执行S.M.A.R.T检测
config_list_foreach main device do_simple_smart_check
@@ -0,0 +1,11 @@
{
"luci-app-smartinfo": {
"description": "Grant UCI access for luci-app-smartinfo",
"read": {
"uci": [ "smartinfo" ]
},
"write": {
"uci": [ "smartinfo" ]
}
}
}
@@ -0,0 +1,4 @@
{
"config": "smartinfo",
"init": "smartinfo"
}