Sync 2026-09-09 01:26:15

This commit is contained in:
github-actions[bot]
2026-09-09 01:26:15 +08:00
parent a179224c4d
commit f8f5792e57
27 changed files with 1113 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-smart-reboot
LUCI_TITLE:=LuCI support for smart-reboot
LUCI_DEPENDS:=+smart-reboot
PKG_LICENSE:=Apache-2.0
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
@@ -0,0 +1,93 @@
'use strict';
'require view';
'require form';
'require network';
'require uci';
return view.extend({
load: function() {
return Promise.all([
network.getNetworks(),
network.getDevices()
]);
},
render: function(data) {
var m, s, o;
var networks = data[0] || [];
var devices = data[1] || [];
var ifaceMap = {};
m = new form.Map('smart-reboot', _('Smart Reboot'),
_('Reboot only when the network is idle at the configured dawn time.'));
s = m.section(form.TypedSection, 'settings', _('Settings'));
s.anonymous = true;
o = s.option(form.Flag, 'enabled', _('Enable'));
o.rmempty = false;
o = s.option(form.DummyValue, 'last_auto_reboot', _('Last automatic reboot'));
o.cfgvalue = function(section_id) {
return uci.get('smart-reboot', section_id, 'last_auto_reboot') || _('Never');
};
o = s.option(form.Value, 'time', _('Reboot time (HH:MM)'));
o.placeholder = '04:00';
o.rmempty = false;
o.validate = function(section_id, value) {
if (!value || !value.match(/^([01][0-9]|2[0-3]):[0-5][0-9]$/))
return _('Time format must be HH:MM (24-hour). Example: 04:00');
return true;
};
o = s.option(form.Flag, 'all_ifaces', _('Select all interfaces'));
o.rmempty = false;
o = s.option(form.MultiValue, 'ifaces', _('Monitored interfaces'));
o.widget = 'select';
o.size = 8;
o.depends('all_ifaces', '0');
o.depends('all_ifaces', '');
networks.forEach(function(netif) {
var logical = netif.getName();
var dev = netif.getL3Device() || netif.getL2Device() || netif.getDevice();
var ifname = dev && dev.getName ? dev.getName() : null;
if (!ifname || ifname === 'lo')
return;
ifaceMap[ifname] = ifaceMap[ifname] || { labels: [] };
if (logical && ifaceMap[ifname].labels.indexOf(logical) < 0)
ifaceMap[ifname].labels.push(logical);
});
(devices || []).forEach(function(dev) {
var name = dev.getName();
if (!name || name === 'lo')
return;
ifaceMap[name] = ifaceMap[name] || { labels: [] };
});
Object.keys(ifaceMap).sort().forEach(function(ifname) {
var labels = ifaceMap[ifname].labels;
var text = labels.length ? '%s (%s)'.format(labels.join(', '), ifname) : ifname;
o.value(ifname, text);
});
o = s.option(form.Value, 'sample_seconds', _('Idle sampling duration (seconds)'));
o.datatype = 'uinteger';
o.placeholder = '120';
o.rmempty = false;
o = s.option(form.Value, 'byte_threshold', _('Idle threshold (bytes)'));
o.datatype = 'uinteger';
o.placeholder = '262144';
o.rmempty = false;
return m.render();
}
});
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: ar\n"
msgid "Smart Reboot"
msgstr "إعادة تشغيل ذكية"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "أعد التشغيل فقط عندما تكون الشبكة خاملة في وقت الفجر المحدد."
msgid "Settings"
msgstr "الإعدادات"
msgid "Enable"
msgstr "تمكين"
msgid "Last automatic reboot"
msgstr "آخر إعادة تشغيل تلقائية"
msgid "Never"
msgstr "أبدًا"
msgid "Reboot time (HH:MM)"
msgstr "وقت إعادة التشغيل (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "يجب أن يكون تنسيق الوقت HH:MM (24 ساعة). مثال: 04:00"
msgid "Select all interfaces"
msgstr "تحديد جميع الواجهات"
msgid "Monitored interfaces"
msgstr "الواجهات المُراقبة"
msgid "Idle sampling duration (seconds)"
msgstr "مدة أخذ عينات الخمول (ثوانٍ)"
msgid "Idle threshold (bytes)"
msgstr "حد الخمول (بايت)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: de\n"
msgid "Smart Reboot"
msgstr "Intelligenter Neustart"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Nur neu starten, wenn das Netzwerk zur konfigurierten Zeit im Leerlauf ist."
msgid "Settings"
msgstr "Einstellungen"
msgid "Enable"
msgstr "Aktivieren"
msgid "Last automatic reboot"
msgstr "Letzter automatischer Neustart"
msgid "Never"
msgstr "Nie"
msgid "Reboot time (HH:MM)"
msgstr "Neustartzeit (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Zeitformat muss HH:MM (24-Stunden) sein. Beispiel: 04:00"
msgid "Select all interfaces"
msgstr "Alle Schnittstellen auswählen"
msgid "Monitored interfaces"
msgstr "Überwachte Schnittstellen"
msgid "Idle sampling duration (seconds)"
msgstr "Leerlauf-Abtastdauer (Sekunden)"
msgid "Idle threshold (bytes)"
msgstr "Leerlauf-Schwellenwert (Bytes)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: es\n"
msgid "Smart Reboot"
msgstr "Reinicio inteligente"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Reiniciar solo cuando la red esté inactiva a la hora de madrugada configurada."
msgid "Settings"
msgstr "Configuración"
msgid "Enable"
msgstr "Habilitar"
msgid "Last automatic reboot"
msgstr "Último reinicio automático"
msgid "Never"
msgstr "Nunca"
msgid "Reboot time (HH:MM)"
msgstr "Hora de reinicio (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "El formato de hora debe ser HH:MM (24 horas). Ejemplo: 04:00"
msgid "Select all interfaces"
msgstr "Seleccionar todas las interfaces"
msgid "Monitored interfaces"
msgstr "Interfaces monitorizadas"
msgid "Idle sampling duration (seconds)"
msgstr "Duración de muestreo de inactividad (segundos)"
msgid "Idle threshold (bytes)"
msgstr "Umbral de inactividad (bytes)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: fr\n"
msgid "Smart Reboot"
msgstr "Redémarrage intelligent"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Redémarrer uniquement lorsque le réseau est inactif à l'heure d'aube configurée."
msgid "Settings"
msgstr "Paramètres"
msgid "Enable"
msgstr "Activer"
msgid "Last automatic reboot"
msgstr "Dernier redémarrage automatique"
msgid "Never"
msgstr "Jamais"
msgid "Reboot time (HH:MM)"
msgstr "Heure de redémarrage (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Le format de l'heure doit être HH:MM (24h). Exemple : 04:00"
msgid "Select all interfaces"
msgstr "Sélectionner toutes les interfaces"
msgid "Monitored interfaces"
msgstr "Interfaces surveillées"
msgid "Idle sampling duration (seconds)"
msgstr "Durée d'échantillonnage d'inactivité (secondes)"
msgid "Idle threshold (bytes)"
msgstr "Seuil d'inactivité (octets)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: id\n"
msgid "Smart Reboot"
msgstr "Reboot Cerdas"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Reboot hanya saat jaringan idle pada waktu dini hari yang dikonfigurasi."
msgid "Settings"
msgstr "Pengaturan"
msgid "Enable"
msgstr "Aktifkan"
msgid "Last automatic reboot"
msgstr "Reboot otomatis terakhir"
msgid "Never"
msgstr "Tidak pernah"
msgid "Reboot time (HH:MM)"
msgstr "Waktu reboot (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Format waktu harus HH:MM (24 jam). Contoh: 04:00"
msgid "Select all interfaces"
msgstr "Pilih semua antarmuka"
msgid "Monitored interfaces"
msgstr "Antarmuka yang dipantau"
msgid "Idle sampling duration (seconds)"
msgstr "Durasi sampling idle (detik)"
msgid "Idle threshold (bytes)"
msgstr "Ambang idle (byte)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: it\n"
msgid "Smart Reboot"
msgstr "Riavvio intelligente"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Riavvia solo quando la rete è inattiva all'ora dell'alba configurata."
msgid "Settings"
msgstr "Impostazioni"
msgid "Enable"
msgstr "Abilita"
msgid "Last automatic reboot"
msgstr "Ultimo riavvio automatico"
msgid "Never"
msgstr "Mai"
msgid "Reboot time (HH:MM)"
msgstr "Ora di riavvio (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Il formato orario deve essere HH:MM (24 ore). Esempio: 04:00"
msgid "Select all interfaces"
msgstr "Seleziona tutte le interfacce"
msgid "Monitored interfaces"
msgstr "Interfacce monitorate"
msgid "Idle sampling duration (seconds)"
msgstr "Durata campionamento inattività (secondi)"
msgid "Idle threshold (bytes)"
msgstr "Soglia inattività (byte)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: ja\n"
msgid "Smart Reboot"
msgstr "スマート再起動"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "設定した早朝時刻に、ネットワークがアイドル状態のときのみ再起動します。"
msgid "Settings"
msgstr "設定"
msgid "Enable"
msgstr "有効化"
msgid "Last automatic reboot"
msgstr "前回の自動再起動"
msgid "Never"
msgstr "なし"
msgid "Reboot time (HH:MM)"
msgstr "再起動時刻 (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "時刻形式は HH:MM(24時間)で入力してください。例: 04:00"
msgid "Select all interfaces"
msgstr "すべてのインターフェースを選択"
msgid "Monitored interfaces"
msgstr "監視対象インターフェース"
msgid "Idle sampling duration (seconds)"
msgstr "アイドル判定サンプリング時間(秒)"
msgid "Idle threshold (bytes)"
msgstr "アイドル閾値(バイト)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\n"
msgid "Smart Reboot"
msgstr "스마트 재부팅"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "설정한 새벽 시각에 네트워크가 유휴 상태일 때만 재부팅합니다."
msgid "Settings"
msgstr "설정"
msgid "Enable"
msgstr "활성화"
msgid "Last automatic reboot"
msgstr "마지막 자동 재부팅"
msgid "Never"
msgstr "없음"
msgid "Reboot time (HH:MM)"
msgstr "재부팅 시각 (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "시간 형식은 HH:MM(24시간제)이어야 합니다. 예: 04:00"
msgid "Select all interfaces"
msgstr "전체 인터페이스 선택"
msgid "Monitored interfaces"
msgstr "모니터링 인터페이스"
msgid "Idle sampling duration (seconds)"
msgstr "유휴 샘플링 시간(초)"
msgid "Idle threshold (bytes)"
msgstr "유휴 임계값(바이트)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: nl\n"
msgid "Smart Reboot"
msgstr "Slimme herstart"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Herstart alleen wanneer het netwerk inactief is op de ingestelde ochtendtijd."
msgid "Settings"
msgstr "Instellingen"
msgid "Enable"
msgstr "Inschakelen"
msgid "Last automatic reboot"
msgstr "Laatste automatische herstart"
msgid "Never"
msgstr "Nooit"
msgid "Reboot time (HH:MM)"
msgstr "Herstarttijd (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Tijdnotatie moet HH:MM (24-uurs) zijn. Voorbeeld: 04:00"
msgid "Select all interfaces"
msgstr "Alle interfaces selecteren"
msgid "Monitored interfaces"
msgstr "Gemonitorde interfaces"
msgid "Idle sampling duration (seconds)"
msgstr "Duur van inactiviteitsmeting (seconden)"
msgid "Idle threshold (bytes)"
msgstr "Inactiviteitsdrempel (bytes)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: pl\n"
msgid "Smart Reboot"
msgstr "Inteligentny restart"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Uruchom ponownie tylko wtedy, gdy sieć jest bezczynna o skonfigurowanej porze nad ranem."
msgid "Settings"
msgstr "Ustawienia"
msgid "Enable"
msgstr "Włącz"
msgid "Last automatic reboot"
msgstr "Ostatni automatyczny restart"
msgid "Never"
msgstr "Nigdy"
msgid "Reboot time (HH:MM)"
msgstr "Godzina restartu (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Format czasu musi być HH:MM (24-godzinny). Przykład: 04:00"
msgid "Select all interfaces"
msgstr "Wybierz wszystkie interfejsy"
msgid "Monitored interfaces"
msgstr "Monitorowane interfejsy"
msgid "Idle sampling duration (seconds)"
msgstr "Czas próbkowania bezczynności (sekundy)"
msgid "Idle threshold (bytes)"
msgstr "Próg bezczynności (bajty)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: pt_BR\n"
msgid "Smart Reboot"
msgstr "Reinicialização inteligente"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Reinicia somente quando a rede estiver ociosa no horário de madrugada configurado."
msgid "Settings"
msgstr "Configurações"
msgid "Enable"
msgstr "Ativar"
msgid "Last automatic reboot"
msgstr "Última reinicialização automática"
msgid "Never"
msgstr "Nunca"
msgid "Reboot time (HH:MM)"
msgstr "Horário de reinicialização (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "O formato de hora deve ser HH:MM (24 horas). Exemplo: 04:00"
msgid "Select all interfaces"
msgstr "Selecionar todas as interfaces"
msgid "Monitored interfaces"
msgstr "Interfaces monitoradas"
msgid "Idle sampling duration (seconds)"
msgstr "Duração da amostragem de ociosidade (segundos)"
msgid "Idle threshold (bytes)"
msgstr "Limite de ociosidade (bytes)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: ru\n"
msgid "Smart Reboot"
msgstr "Умная перезагрузка"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Перезагружать только когда сеть неактивна в заданное раннее время."
msgid "Settings"
msgstr "Настройки"
msgid "Enable"
msgstr "Включить"
msgid "Last automatic reboot"
msgstr "Последняя автоматическая перезагрузка"
msgid "Never"
msgstr "Никогда"
msgid "Reboot time (HH:MM)"
msgstr "Время перезагрузки (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Формат времени должен быть HH:MM (24 часа). Пример: 04:00"
msgid "Select all interfaces"
msgstr "Выбрать все интерфейсы"
msgid "Monitored interfaces"
msgstr "Отслеживаемые интерфейсы"
msgid "Idle sampling duration (seconds)"
msgstr "Длительность проверки простоя (сек.)"
msgid "Idle threshold (bytes)"
msgstr "Порог простоя (байт)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: th\n"
msgid "Smart Reboot"
msgstr "รีบูตอัจฉริยะ"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "รีบูตเฉพาะเมื่อเครือข่ายว่างในเวลาช่วงเช้ามืดที่ตั้งค่าไว้"
msgid "Settings"
msgstr "การตั้งค่า"
msgid "Enable"
msgstr "เปิดใช้งาน"
msgid "Last automatic reboot"
msgstr "รีบูตอัตโนมัติครั้งล่าสุด"
msgid "Never"
msgstr "ไม่เคย"
msgid "Reboot time (HH:MM)"
msgstr "เวลารีบูต (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "รูปแบบเวลาต้องเป็น HH:MM (24 ชั่วโมง) ตัวอย่าง: 04:00"
msgid "Select all interfaces"
msgstr "เลือกทุกอินเทอร์เฟซ"
msgid "Monitored interfaces"
msgstr "อินเทอร์เฟซที่เฝ้าตรวจ"
msgid "Idle sampling duration (seconds)"
msgstr "ระยะเวลาสุ่มตัวอย่างสถานะว่าง (วินาที)"
msgid "Idle threshold (bytes)"
msgstr "เกณฑ์สถานะว่าง (ไบต์)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: tr\n"
msgid "Smart Reboot"
msgstr "Akıllı Yeniden Başlatma"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Yalnızca ağ, ayarlanan şafak saatinde boşta olduğunda yeniden başlat."
msgid "Settings"
msgstr "Ayarlar"
msgid "Enable"
msgstr "Etkinleştir"
msgid "Last automatic reboot"
msgstr "Son otomatik yeniden başlatma"
msgid "Never"
msgstr "Asla"
msgid "Reboot time (HH:MM)"
msgstr "Yeniden başlatma saati (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Saat biçimi HH:MM (24 saat) olmalıdır. Örnek: 04:00"
msgid "Select all interfaces"
msgstr "Tüm arayüzleri seç"
msgid "Monitored interfaces"
msgstr "İzlenen arayüzler"
msgid "Idle sampling duration (seconds)"
msgstr "Boşta örnekleme süresi (saniye)"
msgid "Idle threshold (bytes)"
msgstr "Boşta eşiği (bayt)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: uk\n"
msgid "Smart Reboot"
msgstr "Розумне перезавантаження"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Перезавантажувати лише коли мережа неактивна у заданий ранковий час."
msgid "Settings"
msgstr "Налаштування"
msgid "Enable"
msgstr "Увімкнути"
msgid "Last automatic reboot"
msgstr "Останнє автоматичне перезавантаження"
msgid "Never"
msgstr "Ніколи"
msgid "Reboot time (HH:MM)"
msgstr "Час перезавантаження (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Формат часу має бути HH:MM (24-годинний). Приклад: 04:00"
msgid "Select all interfaces"
msgstr "Вибрати всі інтерфейси"
msgid "Monitored interfaces"
msgstr "Інтерфейси моніторингу"
msgid "Idle sampling duration (seconds)"
msgstr "Тривалість перевірки простою (секунди)"
msgid "Idle threshold (bytes)"
msgstr "Поріг простою (байти)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: vi\n"
msgid "Smart Reboot"
msgstr "Khởi động lại thông minh"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "Chỉ khởi động lại khi mạng nhàn rỗi vào thời điểm rạng sáng đã cấu hình."
msgid "Settings"
msgstr "Cài đặt"
msgid "Enable"
msgstr "Bật"
msgid "Last automatic reboot"
msgstr "Lần khởi động lại tự động gần nhất"
msgid "Never"
msgstr "Chưa từng"
msgid "Reboot time (HH:MM)"
msgstr "Thời gian khởi động lại (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "Định dạng thời gian phải là HH:MM (24 giờ). Ví dụ: 04:00"
msgid "Select all interfaces"
msgstr "Chọn tất cả giao diện"
msgid "Monitored interfaces"
msgstr "Giao diện được giám sát"
msgid "Idle sampling duration (seconds)"
msgstr "Thời lượng lấy mẫu nhàn rỗi (giây)"
msgid "Idle threshold (bytes)"
msgstr "Ngưỡng nhàn rỗi (byte)"
+1
View File
@@ -0,0 +1 @@
zh_Hans
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: zh_Hans\n"
msgid "Smart Reboot"
msgstr "智能重启"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "仅在设定的凌晨时间且网络空闲时才重启。"
msgid "Settings"
msgstr "设置"
msgid "Enable"
msgstr "启用"
msgid "Last automatic reboot"
msgstr "上次自动重启"
msgid "Never"
msgstr "从未"
msgid "Reboot time (HH:MM)"
msgstr "重启时间 (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "时间格式必须为 HH:MM24小时制)。示例:04:00"
msgid "Select all interfaces"
msgstr "选择所有接口"
msgid "Monitored interfaces"
msgstr "监控接口"
msgid "Idle sampling duration (seconds)"
msgstr "空闲采样时长(秒)"
msgid "Idle threshold (bytes)"
msgstr "空闲阈值(字节)"
@@ -0,0 +1,38 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\nLanguage: zh_Hant\n"
msgid "Smart Reboot"
msgstr "智慧重新啟動"
msgid "Reboot only when the network is idle at the configured dawn time."
msgstr "僅在設定的清晨時間且網路閒置時才重新啟動。"
msgid "Settings"
msgstr "設定"
msgid "Enable"
msgstr "啟用"
msgid "Last automatic reboot"
msgstr "上次自動重新啟動"
msgid "Never"
msgstr "從不"
msgid "Reboot time (HH:MM)"
msgstr "重新啟動時間 (HH:MM)"
msgid "Time format must be HH:MM (24-hour). Example: 04:00"
msgstr "時間格式必須為 HH:MM24 小時制)。例如:04:00"
msgid "Select all interfaces"
msgstr "選擇所有介面"
msgid "Monitored interfaces"
msgstr "監控介面"
msgid "Idle sampling duration (seconds)"
msgstr "閒置取樣時長(秒)"
msgid "Idle threshold (bytes)"
msgstr "閒置閾值(位元組)"
@@ -0,0 +1,15 @@
{
"admin/system/smart-reboot": {
"title": "Smart Reboot",
"order": 95,
"action": {
"type": "view",
"path": "system/smart-reboot"
},
"depends": {
"acl": [
"luci-app-smart-reboot"
]
}
}
}
@@ -0,0 +1,15 @@
{
"luci-app-smart-reboot": {
"description": "Grant access to smart-reboot UCI config",
"read": {
"uci": [
"smart-reboot"
]
},
"write": {
"uci": [
"smart-reboot"
]
}
}
}
+47
View File
@@ -0,0 +1,47 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=smart-reboot
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/smart-reboot
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Smart reboot based on network idle state
DEPENDS:=+busybox +uci +ucode +ucode-mod-uci +ucode-mod-log
endef
define Package/smart-reboot/description
Reboot router at configured dawn time only when monitored interfaces are idle.
endef
define Package/smart-reboot/conffiles
/etc/config/smart-reboot
endef
define Build/Compile
true
endef
define Package/smart-reboot/install
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/smart-reboot $(1)/etc/config/smart-reboot
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/smart-reboot $(1)/etc/init.d/smart-reboot
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) ./files/usr/sbin/smart-reboot-check $(1)/usr/sbin/smart-reboot-check
endef
define Package/smart-reboot/postinst
#!/bin/sh
[ -n "$$IPKG_INSTROOT" ] || {
/etc/init.d/smart-reboot enable >/dev/null 2>&1
/etc/init.d/smart-reboot restart >/dev/null 2>&1
}
exit 0
endef
$(eval $(call BuildPackage,smart-reboot))
@@ -0,0 +1,8 @@
config settings 'settings'
option enabled '1'
option time '04:00'
option all_ifaces '0'
option last_auto_reboot ''
list ifaces 'wan'
option sample_seconds '120'
option byte_threshold '262144'
@@ -0,0 +1,68 @@
#!/bin/sh /etc/rc.common
START=95
STOP=10
CRON_FILE="/etc/crontabs/root"
MARKER="# smart-reboot"
. /lib/functions.sh
cron_cleanup() {
[ -f "$CRON_FILE" ] || return 0
sed -i "\\|$MARKER|d" "$CRON_FILE"
}
cron_append() {
local minute="$1"
local hour="$2"
echo "$minute $hour * * * /usr/sbin/smart-reboot-check $MARKER" >> "$CRON_FILE"
}
gen_schedule() {
local enabled hour minute time
config_load smart-reboot
config_get enabled settings enabled '0'
config_get time settings time ''
case "$time" in
[0-1][0-9]:[0-5][0-9]|2[0-3]:[0-5][0-9])
hour="${time%:*}"
minute="${time#*:}"
hour=$((10#$hour))
minute=$((10#$minute))
;;
*)
config_get hour settings hour '4'
config_get minute settings minute '0'
;;
esac
cron_cleanup
[ "$enabled" = "1" ] || return 0
[ -n "$hour" ] || return 0
[ -n "$minute" ] || return 0
cron_append "$minute" "$hour"
}
reload_service() {
start_service
}
start_service() {
[ -f "$CRON_FILE" ] || touch "$CRON_FILE"
gen_schedule
/etc/init.d/cron restart >/dev/null 2>&1
}
stop_service() {
cron_cleanup
/etc/init.d/cron restart >/dev/null 2>&1
}
service_triggers() {
procd_add_reload_trigger "smart-reboot"
}
@@ -0,0 +1,171 @@
#!/usr/bin/ucode
'use strict';
import * as uci from "uci";
import * as log from "log";
import * as fs from "fs";
const CFG = "smart-reboot";
const SECTION = "settings";
const LOCK_FILE = "/var/lock/smart-reboot.lock";
function shquote(s) {
return "'" + replace(s, /'/g, "'\\''") + "'";
}
function cmd_out(cmd) {
let f = fs.popen(cmd, "r");
if (!f)
return "";
let out = f.read("all") ?? "";
f.close();
return trim(out);
}
let cursor = uci.cursor();
function cfg_get(key, def) {
let val = cursor.get(CFG, SECTION, key);
if (val == null)
return def;
if (type(val) == "string" && !length(val))
return def;
return val;
}
function logger(msg) {
log.syslog(log.LOG_INFO, msg);
}
function set_last_auto_reboot() {
let ts = cmd_out("date '+%Y-%m-%d %H:%M:%S'");
cursor.set(CFG, SECTION, "last_auto_reboot", ts);
cursor.commit(CFG);
}
function list_all_ifaces() {
let out = [];
for (let path in fs.glob("/sys/class/net/*")) {
let name = fs.basename(path);
if (name && name != "lo")
push(out, name);
}
return out;
}
function parse_ifaces(raw) {
if (!raw)
return [];
if (type(raw) == "array")
return raw;
return filter(split(raw, /[ \t\r\n]+/), v => length(v));
}
function sum_iface_bytes(ifaces) {
let total = 0;
for (let iface in ifaces) {
if (!iface)
continue;
let rx = trim(fs.readfile(`/sys/class/net/${iface}/statistics/rx_bytes`) ?? "0");
let tx = trim(fs.readfile(`/sys/class/net/${iface}/statistics/tx_bytes`) ?? "0");
total += int(rx || "0") + int(tx || "0");
}
return total;
}
function parse_time(time_str) {
if (!time_str || index(time_str, ":") < 0)
return null;
let parts = split(time_str, ":");
if (length(parts) != 2)
return null;
let hour = int(parts[0]);
let minute = int(parts[1]);
if (hour < 0 || hour > 23 || minute < 0 || minute > 59)
return null;
return { hour, minute };
}
function main() {
log.openlog("smart-reboot", log.LOG_PID);
/*
* Acquire an exclusive non-blocking lock on the lock file using the
* native ucode fs.file.lock() API instead of shelling out to `lock`. This
* avoids spawning a new process on every invocation and is what the
* reviewer suggested.
*/
let lockfd = fs.open(LOCK_FILE, "w+");
if (!lockfd || !lockfd.lock("xn"))
return 0; /* cannot obtain lock */
/* helper to release and close the handle */
function cleanup() {
if (lockfd) {
lockfd.lock("u");
lockfd.close();
lockfd = null;
}
}
let enabled = cfg_get("enabled", "0");
if (enabled != "1") {
cleanup();
return 0;
}
let parsed = parse_time(cfg_get("time", ""));
let hour = parsed ? parsed.hour : int(cfg_get("hour", "4"));
let minute = parsed ? parsed.minute : int(cfg_get("minute", "0"));
let sample_seconds = int(cfg_get("sample_seconds", "120"));
let byte_threshold = int(cfg_get("byte_threshold", "262144"));
let all_ifaces = cfg_get("all_ifaces", "0");
let ifaces = parse_ifaces(cfg_get("ifaces", []));
if (all_ifaces == "1") {
ifaces = list_all_ifaces();
}
else if (!length(ifaces)) {
logger("No monitored interfaces configured. Set smart-reboot.settings.ifaces or enable all_ifaces.");
cleanup();
return 0;
}
let now = localtime(time());
if (now.hour != hour || now.min != minute) {
cleanup();
return 0;
}
let start_bytes = sum_iface_bytes(ifaces);
/* use built-in sleep (milliseconds) instead of shelling out */
sleep(sample_seconds * 1000);
let end_bytes = sum_iface_bytes(ifaces);
let delta = end_bytes - start_bytes;
if (delta <= byte_threshold) {
logger(`Network idle detected (delta=${delta} bytes, threshold=${byte_threshold}), rebooting now`);
set_last_auto_reboot();
system("/sbin/reboot");
}
else {
logger(`Skip reboot, network is active (delta=${delta} bytes, threshold=${byte_threshold})`);
}
/* release lock before exiting */
cleanup();
exit(main());