From 1a7de7026322637ba9a881a36e095a426832df62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:07:22 +0000 Subject: [PATCH 01/14] Bump softprops/action-gh-release in the all-actions group Bumps the all-actions group with 1 update: [softprops/action-gh-release](https://github.com/softprops/action-gh-release). Updates `softprops/action-gh-release` from 2.4.1 to 2.4.2 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2.4.1...v2.4.2) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.4.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/Create-NewReleases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Create-NewReleases.yml b/.github/workflows/Create-NewReleases.yml index 0331864..bd76384 100644 --- a/.github/workflows/Create-NewReleases.yml +++ b/.github/workflows/Create-NewReleases.yml @@ -97,7 +97,7 @@ jobs: # 7--- Publish a GitHub Release with auto-generated notes - name: Create Release with Automated Release Notes - uses: softprops/action-gh-release@v2.4.1 + uses: softprops/action-gh-release@v2.4.2 with: token: ${{ secrets.GITHUB_TOKEN }} tag_name: ${{ steps.nextver.outputs.tag }} From 003ac5ef80dd8ebc404e51d11b6f15bc62042c0a Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:24:10 -0800 Subject: [PATCH 02/14] Minor code improvement. Just a minor code improvement. --- README.md | 4 ++-- uiScribe.sh | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4c6cc19..7192b2d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # uiScribe -## v1.4.9 -### Updated on 2025-Nov-07 +## v1.4.10 +### Updated on 2025-Nov-20 ## About uiScribe updates the System Log page to show log files created by Scribe (syslog-ng). Requires [**Scribe**](https://github.com/cynicastic/scribe) diff --git a/uiScribe.sh b/uiScribe.sh index f426808..398b266 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -13,7 +13,7 @@ ## Forked from https://github.com/jackyaz/uiScribe ## ## ## ######################################################## -# Last Modified: 2025-Nov-04 +# Last Modified: 2025-Nov-16 #------------------------------------------------------- ########### Shellcheck directives ########## @@ -29,8 +29,8 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" -readonly SCRIPT_VERSION="v1.4.9" -readonly SCRIPT_VERSTAG="25110422" +readonly SCRIPT_VERSION="v1.4.10" +readonly SCRIPT_VERSTAG="25111620" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/$SCRIPT_NAME.d" @@ -645,7 +645,7 @@ _Check_WebGUI_Page_Exists_() if [ ! -s "$scriptPageFilePath" ] || \ [ ! -s "$wwwWebPageFilePath" ] || \ - ! diff "$scriptPageFilePath" "$wwwWebPageFilePath" >/dev/null 2>&1 + ! diff -q "$scriptPageFilePath" "$wwwWebPageFilePath" >/dev/null 2>&1 then return 1 fi From ad01e8d8228f85add8cffc8efde991d6c1a2ed24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:42:28 +0000 Subject: [PATCH 03/14] Bump actions/checkout from 5.0.0 to 6.0.0 in the all-actions group Bumps the all-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 5.0.0 to 6.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5.0.0...v6.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: all-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/Create-NewReleases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Create-NewReleases.yml b/.github/workflows/Create-NewReleases.yml index bd76384..ecf1061 100644 --- a/.github/workflows/Create-NewReleases.yml +++ b/.github/workflows/Create-NewReleases.yml @@ -19,7 +19,7 @@ jobs: steps: # 1--- Check out master so we tag the exact merge commit - name: Checkout source code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v6.0.0 with: fetch-depth: 0 ref: 'master' From 4ee1ead2a809b537ee9b9bde12ee4432efcda880 Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sun, 30 Nov 2025 22:27:23 -0800 Subject: [PATCH 04/14] New Features and Improvements 1) Added "Rotate All" and "Rotate Log" on the WebUI page. 2) Added "Clear All" and "Clear Log" on the WebUI page. 3) Added file size information for each log file. --- Main_LogStatus_Content.asp | 29 +- Main_LogStatus_Content.js | 550 +++++++++++++++++++++++++++++-------- README.md | 2 +- uiScribe.sh | 468 ++++++++++++++++++++++++++++--- 4 files changed, 881 insertions(+), 168 deletions(-) diff --git a/Main_LogStatus_Content.asp b/Main_LogStatus_Content.asp index 656855a..74b45b5 100644 --- a/Main_LogStatus_Content.asp +++ b/Main_LogStatus_Content.asp @@ -25,15 +25,16 @@ p{font-weight:bolder}thead.collapsible-jquery{color:#fff;padding:0;width:100%;bo @@ -185,14 +186,18 @@ var clockinterval,bootinterval,timeoutsenabled=!0;function showclock(){JS_timeOb
- +       - + - + +      + +      +
@@ -200,13 +205,17 @@ var clockinterval,bootinterval,timeoutsenabled=!0;function showclock(){JS_timeOb
 
- +
System Messages (click to show/hide)
System Messages (click to show/hide)
- + +      + +      +
diff --git a/Main_LogStatus_Content.js b/Main_LogStatus_Content.js index fe477fd..dd98480 100644 --- a/Main_LogStatus_Content.js +++ b/Main_LogStatus_Content.js @@ -1,7 +1,15 @@ +/**----------------------------**/ +/** Last Modified: 2025-Nov-30 **/ +/**----------------------------**/ + var timeoutsenabled = true; var clockinterval; var bootinterval; +let logFileInfoListInterval = null; +let isInitialLoading = false; + +var logRotate_InfoListArray = []; function showclock() { @@ -21,7 +29,8 @@ function showclock() document.getElementById('log_messages').style.width = '99%'; } -function showbootTime(){ +function showbootTime() +{ Days = Math.floor(boottime / (60*60*24)); Hours = Math.floor((boottime / 3600) % 24); Minutes = Math.floor(boottime % 3600 / 60); @@ -33,25 +42,30 @@ function showbootTime(){ boottime += 1; } -function capitalise(string){ +function capitalise(string) +{ return string.charAt(0).toUpperCase()+string.slice(1); } -function GetCookie(cookiename,returntype){ - if(cookie.get('uiscribe_'+cookiename) != null){ +function GetCookie(cookiename,returntype) +{ + if (cookie.get('uiscribe_'+cookiename) != null) + { return cookie.get('uiscribe_'+cookiename); } - else{ - if(returntype == 'string'){ + else + { + if (returntype == 'string'){ return ''; } - else if(returntype == 'number'){ + else if (returntype == 'number'){ return 0; } } } -function SetCookie(cookiename,cookievalue){ +function SetCookie(cookiename,cookievalue) +{ cookie.set('uiscribe_'+cookiename,cookievalue,10*365); } @@ -67,30 +81,41 @@ $.fn.serializeObject = function(){ return o; }; -function SetCurrentPage(){ +function SetCurrentPage() +{ document.config_form.next_page.value = window.location.pathname.substring(1); document.config_form.current_page.value = window.location.pathname.substring(1); } -function initial(){ +/**----------------------------------------**/ +/** Modified by Martinski W. [2025-Nov-28] **/ +/**----------------------------------------**/ +function initial() +{ + isInitialLoading = true; SetCurrentPage(); LoadCustomSettings(); ScriptUpdateLayout(); + GetLogRotateInfoList(); + setTimeout(GetLogFileInfoList, 7000); show_menu(); showclock(); showbootTime(); clockinterval = setInterval(showclock,1000); bootinterval = setInterval(showbootTime,1000); showDST(); - get_conf_file(); + GetLogsUserTable(); + logFileInfoListInterval = setInterval(GetLogFileInfoList,180000); } -function ScriptUpdateLayout(){ +function ScriptUpdateLayout() +{ var localver = GetVersionNumber('local'); var serverver = GetVersionNumber('server'); $('#uiscribe_version_local').text(localver); - if(localver != serverver && serverver != 'N/A'){ + if (localver != serverver && serverver != 'N/A') + { $('#uiscribe_version_server').text('Updated version available: '+serverver); showhide('btnChkUpdate',false); showhide('uiscribe_version_server',true); @@ -98,133 +123,175 @@ function ScriptUpdateLayout(){ } } -function reload(){ +function reload() +{ location.reload(true); } -function get_logfile(filename){ - var filenamesafe = filename.replace('.log',''); +/**----------------------------------------**/ +/** Modified by Martinski W. [2025-Nov-30] **/ +/**----------------------------------------**/ +function get_logfile(fileName) +{ + let fileNameShort = fileName.replace('.log',''); + $.ajax({ - url: '/ext/uiScribe/'+filename+'.htm', + url: '/ext/uiScribe/'+fileName+'.htm', dataType: 'text', timeout: 3000, - error: function(xhr){ - if(timeoutsenabled == true && window['timeoutenabled_'+filenamesafe] == true){ - window['timeout_'+filenamesafe] = setTimeout(get_logfile,2000,filename); + error: function(xhr) + { + if (timeoutsenabled == true && window['timeoutenabled_'+fileNameShort] == true) + { + window['timeout_'+fileNameShort] = setTimeout(get_logfile,2000,fileName); } }, - success: function(data){ - if(timeoutsenabled == true && window['timeoutenabled_'+filenamesafe] == true){ - if(filename != 'messages'){ - if(data.length > 0){ - document.getElementById('log_'+filename.substring(0,filename.indexOf('.'))).innerHTML = data; - if(document.getElementById('auto_scroll').checked){ - $('#log_'+filename.substring(0,filename.indexOf('.'))).scrollTop(9999999); + success: function(data) + { + let logFileDataElem = document.getElementById('log_'+fileNameShort); + + if (timeoutsenabled == true && window['timeoutenabled_'+fileNameShort] == true) + { + if (data.length === 0) + { + logFileDataElem.innerHTML = '*** The log file is either empty or does not yet exist ***'; + } + if (fileName != 'messages') + { + if (data.length > 0) + { + logFileDataElem.innerHTML = data; + if (document.getElementById('auto_scroll').checked) + { + $('#log_'+fileNameShort).scrollTop(9999999); } } } - else{ - if(data.length > 0){ - document.getElementById('log_'+filename).innerHTML = data; - if(document.getElementById('auto_scroll').checked){ - $('#log_'+filename).scrollTop(9999999); + else + { + if (data.length > 0) + { + logFileDataElem.innerHTML = data; + if (document.getElementById('auto_scroll').checked) + { + $('#log_'+fileName).scrollTop(9999999); } } } - window['timeout_'+filenamesafe] = setTimeout(get_logfile,3000,filename); + window['timeout_'+fileNameShort] = setTimeout(get_logfile,3000,fileName); } } }); } -function get_conf_file(){ +/**----------------------------------------**/ +/** Modified by Martinski W. [2025-Nov-28] **/ +/**----------------------------------------**/ +function GetLogsUserTable() +{ $.ajax({ - url: '/ext/uiScribe/logs.htm', + url: '/ext/uiScribe/logs_user.htm', timeout: 2000, dataType: 'text', - error: function(xhr){ - setTimeout(get_conf_file,1000); + error: function(xhr) + { + setTimeout(GetLogsUserTable,2000); }, - success: function(data){ - var logs=data.split('\n'); - logs.sort(); - logs=logs.filter(Boolean); - + success: function(data) + { + var logFiles = data.split('\n'); + logFiles.sort(); + logFiles = logFiles.filter(Boolean); + var logconfigtablehtml='Logs to display in WebUI'; - - for(var i = 0; i < logs.length; i++){ - var filename=logs[i].substring(logs[i].lastIndexOf('/')+1); - if(filename.indexOf('#') != -1){ - filename = filename.substring(0,filename.indexOf('#')).replace('.log','').replace('.htm','').trim(); - logconfigtablehtml += ''; - logconfigtablehtml += ''; + + for (var i = 0; i < logFiles.length; i++) + { + var fileName = logFiles[i].substring(logFiles[i].lastIndexOf('/')+1); + if (fileName.indexOf('#') != -1) + { + fileName = fileName.substring(0,fileName.indexOf('#')).replace('.log','').replace('.htm','').trim(); + logconfigtablehtml += ''; + logconfigtablehtml += ''; } - else{ - filename = filename.replace(".log","").replace(".htm","").trim(); - logconfigtablehtml += ''; - logconfigtablehtml += ''; + else + { + fileName = fileName.replace(".log","").replace(".htm","").trim(); + logconfigtablehtml += ''; + logconfigtablehtml += ''; } - if((i+1) % 4 == 0){ + if ((i+1) % 4 == 0) + { logconfigtablehtml += '
'; } } - + logconfigtablehtml += ''; logconfigtablehtml += ''; logconfigtablehtml += ''; logconfigtablehtml += ''; logconfigtablehtml += ''; $('#table_config').append(logconfigtablehtml); - logs.reverse(); - - for(var i = 0; i < logs.length; i++){ - var commentstart=logs[i].indexOf('#'); - if(commentstart != -1){ - continue - } - filename=logs[i].substring(logs[i].lastIndexOf('/')+1); - $('#table_messages').after(BuildLogTable(filename)); + logFiles.reverse(); + + for (var i = 0; i < logFiles.length; i++) + { + var commentstart = logFiles[i].indexOf('#'); + if (commentstart != -1) { continue; } + fileName = logFiles[i].substring(logFiles[i].lastIndexOf('/')+1); + $('#table_messages').after(BuildLogTable(fileName)); } - + + let logFileInfoStr = GetLogFileSizeInfo('messages'); + document.getElementById('fileTitle_messages').innerHTML = logFileInfoStr + '   (click to show/hide)' AddEventHandlers(); + isInitialLoading = false; } }); } -function DownloadAllLogFile(){ +function DownloadAllLogFiles() +{ $('.btndownload').each(function(index){$(this).trigger('click');}); } -function DownloadLogFile(btnlog){ - $(btnlog).prop('disabled',true); - $(btnlog).addClass('btndisabled'); +/**----------------------------------------**/ +/** Modified by Martinski W. [2025-Nov-28] **/ +/**----------------------------------------**/ +function DownloadLogFile(btnLog) +{ + $(btnLog).prop('disabled',true); + $(btnLog).addClass('btndisabled'); var filepath = ''; - if(btnlog.name == 'btnmessages'){ + if (btnLog.name === 'btnDownload_messages') + { filepath='/ext/uiScribe/messages.htm'; } - else{ - filepath='/ext/uiScribe/'+btnlog.name.replace('btn','')+'.log.htm'; + else + { + filepath='/ext/uiScribe/'+btnLog.name.replace('btnDownload_','')+'.log.htm'; } fetch(filepath).then(resp => resp.blob()).then(blob => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; - a.download = btnlog.name.replace('btn','')+'.log'; + a.download = btnLog.name.replace('btnDownload_','')+'.log'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); - $(btnlog).prop('disabled',false); - $(btnlog).removeClass('btndisabled'); + $(btnLog).prop('disabled',false); + $(btnLog).removeClass('btndisabled'); }) .catch(() => { console.log('File download failed!'); - $(btnlog).prop('disabled',false); - $(btnlog).removeClass('btndisabled'); + $(btnLog).prop('disabled',false); + $(btnLog).removeClass('btndisabled'); }); } -function update_status(){ +function update_status() +{ $.ajax({ url: '/ext/uiScribe/detect_update.js', dataType: 'script', @@ -232,19 +299,24 @@ function update_status(){ error: function(xhr){ setTimeout(update_status,1000); }, - success: function(){ - if(updatestatus == 'InProgress'){ + success: function() + { + if (updatestatus == 'InProgress') + { setTimeout(update_status,1000); } - else{ + else + { document.getElementById('imgChkUpdate').style.display = 'none'; showhide('uiscribe_version_server',true); - if(updatestatus != 'None'){ + if (updatestatus != 'None') + { $('#uiscribe_version_server').text('Updated version available: '+updatestatus); showhide('btnChkUpdate',false); showhide('btnDoUpdate',true); } - else{ + else + { $('#uiscribe_version_server').text('No update available'); showhide('btnChkUpdate',true); showhide('btnDoUpdate',false); @@ -254,7 +326,103 @@ function update_status(){ }); } -function CheckUpdate(){ +var logRotateStatus = ''; + +/**-------------------------------------**/ +/** Added by Martinski W. [2025-Nov-28] **/ +/**-------------------------------------**/ +function Update_LogRotate_Status(logObj) +{ + $.ajax({ + url: '/ext/uiScribe/logRotateStatus.js', + dataType: 'script', + timeout: 3000, + error: function(xhr){ + setTimeout(Update_LogRotate_Status,1000,logObj); + }, + success: function() + { + let theStatus = ''; + if (logRotateStatus === 'InProgress') + { + setTimeout(Update_LogRotate_Status,2000,logObj); + } + else if (logRotateStatus === 'ERROR') + { + theStatus = logRotateStatus; + } + else if (logRotateStatus === 'DONE') + { + theStatus = logRotateStatus; + } + $(logObj).prop('disabled',false); + $(logObj).removeClass('btndisabled'); + document.getElementById(logObj.id).style.display = ''; + document.getElementById('imgChkUpdate').style.display = 'none'; + } + }); +} + +/**-------------------------------------**/ +/** Added by Martinski W. [2025-Nov-28] **/ +/**-------------------------------------**/ +function RotateLogFile(logObj, logFileName) +{ + if (typeof logFileInfoListInterval !== 'undefined' && logFileInfoListInterval !== null) + { + clearInterval(logFileInfoListInterval); + logFileInfoListInterval = null; + } + + $(logObj).prop('disabled',true); + $(logObj).addClass('btndisabled'); + + let waitValue = 30; + if (logFileName === 'ALL') + { + if (logRotate_InfoListArray.length > 5) + { waitValue = 60; } + else + { waitValue = 45; } + } + let actionScriptVal = 'start_uiScribeRotateLog_' + logFileName; + document.config_form.action_script.value = actionScriptVal; + document.config_form.action_wait.value = waitValue; + showLoading(); + document.config_form.submit(); +} + +/**-------------------------------------**/ +/** Added by Martinski W. [2025-Nov-28] **/ +/**-------------------------------------**/ +function ClearLogFile(logObj, logFileName) +{ + if (typeof logFileInfoListInterval !== 'undefined' && logFileInfoListInterval !== null) + { + clearInterval(logFileInfoListInterval); + logFileInfoListInterval = null; + } + + $(logObj).prop('disabled',true); + $(logObj).addClass('btndisabled'); + + let waitValue = 30; + if (logFileName === 'ALL') + { + if (logRotate_InfoListArray.length > 5) + { waitValue = 60; } + else + { waitValue = 45; } + } + let actionScriptVal = 'start_uiScribeClearLog_' + logFileName; + document.config_form.action_script.value = actionScriptVal; + document.config_form.action_wait.value = waitValue; + showLoading(); + document.config_form.submit(); +} + +function CheckUpdate() +{ showhide('btnChkUpdate',false); document.formScriptActions.action_script.value='start_uiScribecheckupdate'; document.formScriptActions.submit(); @@ -262,14 +430,25 @@ function CheckUpdate(){ setTimeout(update_status,2000); } -function DoUpdate(){ +function DoUpdate() +{ document.config_form.action_script.value = 'start_uiScribedoupdate'; document.config_form.action_wait.value = 10; showLoading(); document.config_form.submit(); } -function SaveConfig(){ +/**----------------------------------------**/ +/** Modified by Martinski W. [2025-Nov-28] **/ +/**----------------------------------------**/ +function SaveConfig() +{ + if (typeof logFileInfoListInterval !== 'undefined' && logFileInfoListInterval !== null) + { + clearInterval(logFileInfoListInterval); + logFileInfoListInterval = null; + } + document.getElementById('amng_custom').value = JSON.stringify($('config_form').serializeObject()); document.config_form.action_script.value = 'start_uiScribeconfig'; document.config_form.action_wait.value = 5; @@ -277,16 +456,17 @@ function SaveConfig(){ document.config_form.submit(); } -function GetVersionNumber(versiontype){ +function GetVersionNumber(versiontype) +{ var versionprop; - if(versiontype == 'local'){ + if (versiontype == 'local'){ versionprop = custom_settings.uiscribe_version_local; } - else if(versiontype == 'server'){ + else if (versiontype == 'server'){ versionprop = custom_settings.uiscribe_version_server; } - if(typeof versionprop == 'undefined' || versionprop == null){ + if (typeof versionprop == 'undefined' || versionprop == null){ return 'N/A'; } else{ @@ -294,34 +474,155 @@ function GetVersionNumber(versiontype){ } } -function BuildLogTable(name){ +/**-------------------------------------**/ +/** Added by Martinski W. [2025-Nov-28] **/ +/**-------------------------------------**/ +function GetLogRotateInfoList() +{ + $.ajax({ + url: '/ext/uiScribe/logRotateInfoList.js', + dataType: 'script', + timeout: 1000, + error: function(xhr){ + setTimeout(GetLogRotateInfoList, 1000); + }, + success: function() + { + if (logRotate_InfoListArray.length === 0) + { return false; } + if (isInitialLoading) { return true; } + SetLogFileSizeInfo(); + } + }); +} + +/**-------------------------------------**/ +/** Added by Martinski W. [2025-Nov-28] **/ +/**-------------------------------------**/ +function GetLogFileInfoList() +{ + document.formScriptActions.action_script.value='start_uiScribeLogFileInfoList'; + document.formScriptActions.submit(); + setTimeout(GetLogRotateInfoList,3000); +} + +/**-------------------------------------**/ +/** Added by Martinski W. [2025-Nov-28] **/ +/**-------------------------------------**/ +function SetLogFileSizeInfo() +{ + $.ajax({ + url: '/ext/uiScribe/logs_user.htm', + timeout: 2000, + dataType: 'text', + error: function(xhr) + { + setTimeout(SetLogFileSizeInfo,2000); + }, + success: function(data) + { + let logFileName, fileNameShort, logFileTitleElem, logFileInfoStr; + let logFiles = data.split('\n'); + logFiles.sort(); + logFiles = logFiles.filter(Boolean); + + for (var indx = 0; indx < logFiles.length; indx++) + { + var commentstart = logFiles[indx].indexOf('#'); + if (commentstart != -1) { continue; } + logFileName = logFiles[indx].substring(logFiles[indx].lastIndexOf('/')+1); + fileNameShort = logFileName.replace('.log',''); + + logFileTitleElem = document.getElementById('fileTitle_' + fileNameShort); + if (typeof logFileTitleElem !== 'undefined' && logFileTitleElem !== null) + { + logFileInfoStr = GetLogFileSizeInfo(logFileName); + logFileTitleElem.innerHTML = logFileInfoStr + '   (click to show/hide)' + } + } + + logFileTitleElem = document.getElementById('fileTitle_messages'); + if (typeof logFileTitleElem !== 'undefined' && logFileTitleElem !== null) + { + logFileInfoStr = GetLogFileSizeInfo('messages'); + logFileTitleElem.innerHTML = logFileInfoStr + '   (click to show/hide)' + } + } + }); +} + +/**-------------------------------------**/ +/** Added by Martinski W. [2025-Nov-28] **/ +/**-------------------------------------**/ +function GetLogFileSizeInfo(theFileName) +{ + let logFilePath, logFileSize, logFileName, logFileInfoStr; + let fileSizeOK = false; + + for (var indx = 0; indx < logRotate_InfoListArray.length; indx++) + { + logFilePath = logRotate_InfoListArray[indx].LOG_PATH0; + logFileSize = logRotate_InfoListArray[indx].LOG_SIZE0; + logFileName = logFilePath.replace('/opt/var/log/',''); + if (logFileName === theFileName) + { fileSizeOK = true; break; } + } + + if (logFileSize === '' || !fileSizeOK) + { logFileInfoStr = theFileName; } + else + { logFileInfoStr = theFileName + ' [' + logFileSize + ']'; } + + return logFileInfoStr; +} + +/**----------------------------------------**/ +/** Modified by Martinski W. [2025-Nov-28] **/ +/**----------------------------------------**/ +function BuildLogTable(logFileName) +{ + let logFileInfoStr = GetLogFileSizeInfo(logFileName); + let fileNameShort = logFileName.substring(0,logFileName.indexOf('.')); + var loghtml = '
 
'; - loghtml += ''; - loghtml += ''; + loghtml += '
'+name+' (click to show/hide)
'; + loghtml += ''; + loghtml += ''; + loghtml += ''; loghtml += '
'+logFileInfoStr+'   (click to show/hide)
'; - loghtml += ''; + loghtml += ''; loghtml += '
'; - loghtml += ''; + loghtml += ''; + loghtml += '     '; + loghtml += ''; + loghtml += '     '; + loghtml += ''; + loghtml += '
'; + return loghtml; } -function AddEventHandlers(){ +function AddEventHandlers() +{ $('.collapsible-jquery').off('click').on('click',function(){ var filename = $(this).prop('id').replace('thead_',''); - if(filename != 'messages'){ + if (filename != 'messages') + { filename += '.log'; } - var filenamesafe = filename.replace('.log',''); - if($(this).siblings().is(':hidden') == true){ - window['timeoutenabled_'+filenamesafe] = true; + var fileNameShort = filename.replace('.log',''); + if ($(this).siblings().is(':hidden') == true) + { + window['timeoutenabled_'+fileNameShort] = true; get_logfile(filename); } - else{ - clearTimeout(window['timeout_'+filenamesafe]); - window['timeoutenabled_'+filenamesafe] = false; + else + { + clearTimeout(window['timeout_'+fileNameShort]); + window['timeoutenabled_'+fileNameShort] = false; } $(this).siblings().toggle('fast'); }); @@ -332,58 +633,71 @@ function AddEventHandlers(){ $('.collapsible-jquery-config').off('click').on('click',function(){ $(this).siblings().toggle('fast',function(){ - if($(this).css('display') == 'none'){ + if ($(this).css('display') == 'none') + { SetCookie($(this).siblings()[0].id,'collapsed'); } - else{ + else + { SetCookie($(this).siblings()[0].id,'expanded'); } }) }); $('.collapsible-jquery-config').each(function(index,element){ - if(GetCookie($(this)[0].id,'string') == 'collapsed'){ + if (GetCookie($(this)[0].id,'string') == 'collapsed') + { $(this).siblings().toggle(false); } - else{ + else + { $(this).siblings().toggle(true); } }); } -function ToggleRefresh(){ - if($('#auto_refresh').prop('checked') == true){ +function ToggleRefresh() +{ + if ($('#auto_refresh').prop('checked') == true) + { $('#auto_scroll').prop('disabled',false) - timeoutsenabled=true; + timeoutsenabled = true; $('.collapsible-jquery').each(function(index,element){ var filename = $(this).prop('id').replace('thead_',''); - if(filename != 'messages'){ + if (filename != 'messages') + { filename += '.log'; } - if($(this).siblings().is(':hidden') == false){ + if ($(this).siblings().is(':hidden') == false) + { get_logfile(filename); } }); } - else{ + else + { $('#auto_scroll').prop('disabled',true) - timeoutsenabled=false; + timeoutsenabled = false; } } -function ResizeAll(action){ +function ResizeAll(action) +{ $('.collapsible-jquery').each(function(index,element){ - if(action == 'show'){ + if (action == 'show') + { $(this).siblings().toggle(true); var filename = $(this).prop('id').replace('thead_',''); window['timeoutenabled_'+filename] = true; - if(filename != 'messages'){ + if (filename != 'messages') + { filename += '.log'; } get_logfile(filename); } - else{ + else + { $(this).siblings().toggle(false); var filename = $(this).prop('id').replace('thead_',''); window['timeoutenabled_'+filename] = false; diff --git a/README.md b/README.md index 7192b2d..258f581 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # uiScribe ## v1.4.10 -### Updated on 2025-Nov-20 +### Updated on 2025-Nov-30 ## About uiScribe updates the System Log page to show log files created by Scribe (syslog-ng). Requires [**Scribe**](https://github.com/cynicastic/scribe) diff --git a/uiScribe.sh b/uiScribe.sh index 398b266..ad049a5 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -13,7 +13,7 @@ ## Forked from https://github.com/jackyaz/uiScribe ## ## ## ######################################################## -# Last Modified: 2025-Nov-16 +# Last Modified: 2025-Nov-30 #------------------------------------------------------- ########### Shellcheck directives ########## @@ -30,15 +30,15 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" readonly SCRIPT_VERSION="v1.4.10" -readonly SCRIPT_VERSTAG="25111620" +readonly SCRIPT_VERSTAG="25113022" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" -readonly SCRIPT_DIR="/jffs/addons/$SCRIPT_NAME.d" +readonly SCRIPT_DIR="/jffs/addons/${SCRIPT_NAME}.d" readonly SCRIPT_PAGE_DIR="$(readlink -f /www/user)" -readonly SCRIPT_WEB_DIR="$SCRIPT_PAGE_DIR/$SCRIPT_NAME" +readonly SCRIPT_WEB_DIR="${SCRIPT_PAGE_DIR}/$SCRIPT_NAME" readonly SHARED_DIR="/jffs/addons/shared-jy" readonly SHARED_REPO="https://raw.githubusercontent.com/AMTM-OSR/shared-jy/master" -readonly SHARED_WEB_DIR="$SCRIPT_PAGE_DIR/shared-jy" +readonly SHARED_WEB_DIR="${SCRIPT_PAGE_DIR}/shared-jy" [ -z "$(nvram get odmpid)" ] && ROUTER_MODEL="$(nvram get productid)" || ROUTER_MODEL="$(nvram get odmpid)" ##-------------------------------------## @@ -50,6 +50,27 @@ readonly branchxStr_TAG="[Branch: $SCRIPT_BRANCH]" readonly versionDev_TAG="${SCRIPT_VERSION}_${SCRIPT_VERSTAG}" readonly versionMod_TAG="$SCRIPT_VERSION on $ROUTER_MODEL" +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +readonly oneKByte=1024 +readonly oneMByte=1048576 +readonly oneGByte=1073741824 +readonly optTempDir="/opt/tmp" +readonly optVarLogDir="/opt/var/log" +readonly logRotateStr="logrotate" +readonly logRotateCmd="/opt/sbin/$logRotateStr" +readonly logRotateDir="/opt/etc/${logRotateStr}.d" +readonly logRotateTemp="${optTempDir}/${logRotateStr}.temp" +readonly logRotateDaily="${optTempDir}/${logRotateStr}.daily" +readonly logRotateOutput="${optTempDir}/${logRotateStr}.out" +readonly logRotateConfig="/opt/etc/${logRotateStr}.conf" +readonly logRotateStatusT="${optTempDir}/${logRotateStr}.status" +readonly logRotateStatusJS="${SCRIPT_WEB_DIR}/logRotateStatus.js" +readonly logRotateInfoListJS="${SCRIPT_DIR}/logRotateInfoList.js" +readonly logClearStatusT="${optTempDir}/${logRotateStr}Clear.status" +readonly logClearStatusJS="${SCRIPT_WEB_DIR}/logClearStatus.js" + ### End of script variables ### ### Start of output format variables ### @@ -344,6 +365,9 @@ Validate_Number() fi } +##----------------------------------------## +## Modified by Martinski W. [2025-Nov-28] ## +##----------------------------------------## Create_Dirs() { if [ ! -d "$SCRIPT_DIR" ]; then @@ -357,10 +381,18 @@ Create_Dirs() if [ ! -d "$SCRIPT_WEB_DIR" ]; then mkdir -p "$SCRIPT_WEB_DIR" fi + + if [ ! -d "$optTempDir" ]; then + mkdir -m 775 "$optTempDir" 2>/dev/null + fi + + if [ ! -d "$optVarLogDir" ]; then + mkdir -m 755 "$optVarLogDir" 2>/dev/null + fi } ##----------------------------------------## -## Modified by Martinski W. [2025-Jun-15] ## +## Modified by Martinski W. [2025-Nov-28] ## ##----------------------------------------## Create_Symlinks() { @@ -377,31 +409,39 @@ Create_Symlinks() then rm -f "$SCRIPT_DIR/.logs_user" fi - - if [ ! -f "$SCRIPT_DIR/.logs_user" ]; then + if [ ! -f "$SCRIPT_DIR/.logs_user" ] + then touch "$SCRIPT_DIR/.logs_user" fi while IFS='' read -r line || [ -n "$line" ] do - if [ "$(grep -c "$line" "$SCRIPT_DIR/.logs_user")" -eq 0 ]; then - printf "%s\\n" "$line" >> "$SCRIPT_DIR/.logs_user" + if [ "$(grep -c "$line" "$SCRIPT_DIR/.logs_user")" -eq 0 ] + then + printf "%s\n" "$line" >> "$SCRIPT_DIR/.logs_user" fi done < "$SCRIPT_DIR/.logs" rm -f "$SCRIPT_WEB_DIR/"*.htm 2>/dev/null - ln -s "$SCRIPT_DIR/.logs_user" "$SCRIPT_WEB_DIR/logs.htm" 2>/dev/null - ln -s /opt/var/log/messages "$SCRIPT_WEB_DIR/messages.htm" 2>/dev/null + ln -s "${optVarLogDir}/messages" "$SCRIPT_WEB_DIR/messages.htm" 2>/dev/null + ln -s "$SCRIPT_DIR/.logs_user" "$SCRIPT_WEB_DIR/logs_user.htm" 2>/dev/null + while IFS='' read -r line || [ -n "$line" ] do ln -s "$line" "$SCRIPT_WEB_DIR/$(basename "$line").htm" 2>/dev/null done < "$SCRIPT_DIR/.logs" + _Get_LogRotate_FileInfoList_ + ln -s "$logRotateInfoListJS" "${SCRIPT_WEB_DIR}/logRotateInfoList.js" 2>/dev/null + if [ ! -d "$SHARED_WEB_DIR" ]; then ln -s "$SHARED_DIR" "$SHARED_WEB_DIR" 2>/dev/null fi } +##----------------------------------------## +## Modified by Martinski W. [2025-Nov-28] ## +##----------------------------------------## Logs_FromSettings() { SETTINGSFILE="/jffs/addons/custom_settings.txt" @@ -418,13 +458,14 @@ Logs_FromSettings() syslog-ng --preprocess-into="$SCRIPT_DIR/tmplogs.txt" && grep -A 1 "destination" "$SCRIPT_DIR/tmplogs.txt" | grep "file(\"" | grep -v "#" | grep -v "messages" | sed -e 's/file("//;s/".*$//' | awk '{$1=$1;print}' > "$SCRIPT_DIR/.logs" rm -f "$SCRIPT_DIR/tmplogs.txt" 2>/dev/null - echo "" > "$LOGS_USER" + echo > "$LOGS_USER" comment=" #excluded#" while IFS='' read -r line || [ -n "$line" ] do - if [ "$(grep -c "$line" "$LOGS_USER")" -eq 0 ]; then - printf "%s%s\\n" "$line" "$comment" >> "$LOGS_USER" + if [ "$(grep -c "$line" "$LOGS_USER")" -eq 0 ] + then + printf "%s%s\n" "$line" "$comment" >> "$LOGS_USER" fi done < "$SCRIPT_DIR/.logs" @@ -432,8 +473,8 @@ Logs_FromSettings() do loglinenumber="$(grep -n "$log" "$LOGS_USER" | cut -f1 -d':')" logline="$(sed "$loglinenumber!d" "$LOGS_USER" | awk '{$1=$1};1')" - - if echo "$logline" | grep -q "#excluded" ; then + if echo "$logline" | grep -q "#excluded" + then sed -i "$loglinenumber"'s/ #excluded#//' "$LOGS_USER" fi done @@ -442,13 +483,17 @@ Logs_FromSettings() mv -f /tmp/uiscribe-logs "$LOGS_USER" rm -f "$SCRIPT_WEB_DIR/"*.htm 2>/dev/null - ln -s "$SCRIPT_DIR/.logs_user" "$SCRIPT_WEB_DIR/logs.htm" 2>/dev/null - ln -s /opt/var/log/messages "$SCRIPT_WEB_DIR/messages.htm" 2>/dev/null + ln -s "${optVarLogDir}/messages" "$SCRIPT_WEB_DIR/messages.htm" 2>/dev/null + ln -s "$SCRIPT_DIR/.logs_user" "$SCRIPT_WEB_DIR/logs_user.htm" 2>/dev/null + while IFS='' read -r line || [ -n "$line" ] do ln -s "$line" "$SCRIPT_WEB_DIR/$(basename "$line").htm" 2>/dev/null done < "$SCRIPT_DIR/.logs" + _Get_LogRotate_FileInfoList_ + ln -s "$logRotateInfoListJS" "${SCRIPT_WEB_DIR}/logRotateInfoList.js" 2>/dev/null + Print_Output true "Merge of updated logs from WebUI completed successfully" "$PASS" else Print_Output true "No updated logs from WebUI found, no merge into $LOGS_USER necessary" "$PASS" @@ -463,20 +508,16 @@ Generate_Log_List() { ScriptHeader goback=false - printf "Retrieving list of log files...\n\n" + printf " Retrieving list of log files...\n\n" logCount="$(wc -l < "$SCRIPT_DIR/.logs_user")" COUNTER=1 until [ "$COUNTER" -gt "$logCount" ] do logfile="$(sed "$COUNTER!d" "$SCRIPT_DIR/.logs_user" | awk '{$1=$1};1')" - if [ "$COUNTER" -lt 10 ]; then - printf "%s) %s\n" "$COUNTER" "$logfile" - else - printf "%s) %s\n" "$COUNTER" "$logfile" - fi + printf "%2d) %s\n" "$COUNTER" "$logfile" COUNTER="$((COUNTER + 1))" done - printf "\ne) Go back\n" + printf "\n e) Go back\n" while true do @@ -626,6 +667,343 @@ Auto_Startup() esac } +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +_GetFileSize_() +{ + local typeUnits sizeUnits sizeInfo fileSize + if [ $# -eq 0 ] || [ -z "$1" ] || [ ! -f "$1" ] + then echo 0 ; return 1 + fi + + if [ $# -lt 2 ] || [ -z "$2" ] || \ + ! echo "$2" | grep -qE "^(B|KB|MB|GB|HR|HRx)$" + then typeUnits="B" ; else typeUnits="$2" + fi + + _GetNum_() { printf "%.1f" "$(echo "$1" | awk "{print $1}")" ; } + + case "$typeUnits" in + B|KB|MB|GB) + fileSize="$(ls -1l "$1" | awk -F ' ' '{print $3}')" + case "$typeUnits" in + KB) fileSize="$(_GetNum_ "($fileSize / $oneKByte)")" ;; + MB) fileSize="$(_GetNum_ "($fileSize / $oneMByte)")" ;; + GB) fileSize="$(_GetNum_ "($fileSize / $oneGByte)")" ;; + esac + echo "$fileSize" + ;; + HR|HRx) + fileSize="$(ls -1lh "$1" | awk -F ' ' '{print $3}')" + sizeInfo="${fileSize}B" + sizeUnits="$(echo "$sizeInfo" | tr -d '.0-9')" + if [ "$typeUnits" = "HR" ] + then + [ "$sizeUnits" = "B" ] && \ + sizeInfo="$(echo "$sizeInfo" | grep -oE '[0-9]+') Bytes" + echo "$sizeInfo" + return 0 + fi + case "$sizeUnits" in + MB) fileSize="$(_GetFileSize_ "$1" KB)" + sizeInfo="$sizeInfo (${fileSize}KB)" + ;; + GB) fileSize="$(_GetFileSize_ "$1" MB)" + sizeInfo="$sizeInfo (${fileSize}MB)" + ;; + B) sizeInfo="$(echo "$sizeInfo" | grep -oE '[0-9]+') Bytes" + ;; + esac + echo "$sizeInfo" + ;; + *) echo 0 ;; + esac + return 0 +} + +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +_Get_LogRotate_ConfigFile_() +{ + if [ $# -eq 0 ] || [ -z "$1" ] || \ + [ ! -s "${optVarLogDir}/$1" ] + then + echo ; return 1 + fi + local theConfigFile theConfLogExp logFileRegExp configFileOK + + configFileOK=false + theConfLogExp="${logRotateDir}/*" + logFileRegExp="${optVarLogDir}/.*([.]log)?" + + for theConfigFile in $(ls -1 $theConfLogExp 2>/dev/null) + do + if [ ! -s "$theConfigFile" ] || \ + ! grep -qE "$logFileRegExp" "$theConfigFile" + then continue + fi + if grep -qE "${optVarLogDir}/$1" "$theConfigFile" + then + configFileOK=true ; break + fi + done + + "$configFileOK" && echo "$theConfigFile" || echo +} + +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +_Get_LogRotate_FileInfoList_() +{ + local theConfLogExp theConfigFile theConfigCount + local logFileList logFileCount logFileSize logFileRegExp + + { + printf 'var logRotate_InfoListArray =' + } > "$logRotateInfoListJS" + + theConfigCount=0 + theConfLogExp="${logRotateDir}/*" + logFileRegExp="${optVarLogDir}/(.*|[.]log)" + + for theConfigFile in $(ls -1 $theConfLogExp 2>/dev/null) + do + if [ ! -s "$theConfigFile" ] || \ + ! grep -qE "$logFileRegExp" "$theConfigFile" + then continue + fi + logFileList="$(grep -oE "$logFileRegExp" "$theConfigFile" | awk -F' ' '{print $1}')" + [ -z "$logFileList" ] && continue + + if [ "$theConfigCount" -gt 0 ] + then printf ',\n' >> "$logRotateInfoListJS" + else printf '\n[\n' >> "$logRotateInfoListJS" + fi + { + printf " { LR_CONFIG: '${theConfigFile}'," + } >> "$logRotateInfoListJS" + + logFileCount=0 + for logFPath in $logFileList + do + if [ "$logFileCount" -eq 0 ] + then printf '\n' >> "$logRotateInfoListJS" + else printf ',\n' >> "$logRotateInfoListJS" + fi + logFileSize="$(_GetFileSize_ "$logFPath" HRx)" + [ "$logFileSize" = "0" ] && logFileSize="0 Bytes" + { + printf " LOG_PATH${logFileCount}: '%s',\n" "$logFPath" + printf " LOG_SIZE${logFileCount}: '%s'" "$logFileSize" + } >> "$logRotateInfoListJS" + logFileCount="$((logFileCount + 1))" + done + { + printf '\n }' + } >> "$logRotateInfoListJS" + theConfigCount="$((theConfigCount + 1))" + done + + if [ "$theConfigCount" -eq 0 ] + then + printf ' [];\n' >> "$logRotateInfoListJS" + else + printf '\n];\n' >> "$logRotateInfoListJS" + fi +} + +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +_Run_RotateLogFile_() +{ + rm -f "$logRotateStatusJS" + + if [ $# -eq 0 ] || [ -z "$1" ] || [ ! -x "$logRotateCmd" ] + then + echo "var logRotateStatus = 'ERROR';" > "$logRotateStatusJS" + echo "ERROR: LogRotate is NOT available." > "$logRotateStatusT" + return 1 + fi + local logRotateConf="" + + case "$1" in + ALL) logRotateConf="$logRotateConfig" + ;; + *) logRotateConf="$(_Get_LogRotate_ConfigFile_ "$1")" + ;; + esac + + if [ -z "$logRotateConf" ] || [ ! -s "$logRotateConf" ] + then + echo "var logRotateStatus = 'ERROR';" > "$logRotateStatusJS" + { + [ ! -s "${optVarLogDir}/$1" ] && \ + echo "Log file [${optVarLogDir}/$1] NOT found or is EMPTY." + [ -n "$logRotateConf" ] && \ + echo "Check if LogRotate config file ["$logRotateConf"] exists." + } > "$logRotateStatusT" + return 1 + fi + echo "var logRotateStatus = 'InProgress';" > "$logRotateStatusJS" + + $logRotateCmd "$logRotateConf" > "$logRotateOutput" 2>&1 + tail -v "$logRotateOutput" > "$logRotateStatusT" + [ -s "$logRotateOutput" ] && \ + cat "$logRotateOutput" > "$logRotateDaily" + echo "LogRotate '$1' was completed." >> "$logRotateStatusT" + echo "var logRotateStatus = 'DONE';" > "$logRotateStatusJS" + + sleep 1 + _Get_LogRotate_FileInfoList_ +} + +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +_Set_LogRotateClear_ConfigOptions_() +{ + cat << 'EOF' +{ + hourly + size 0k + rotate 9 + compress + create + dateext + dateformat -%Y%m%d%H%M%S + missingok + notifempty + sharedscripts + postrotate + /usr/bin/killall -HUP syslog-ng + endscript +} +EOF +} + +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +_Get_LogRotateClear_ConfigFile_() +{ + if [ $# -eq 0 ] || [ -z "$1" ] || \ + [ ! -s "${optVarLogDir}/$1" ] + then + echo ; return 1 + fi + local logFileName="$1" theConfigFile + theConfigFile="${optTempDir}/ClearLog_${logFileName%.*}.conf" + rm -f "$theConfigFile" + + echo "${optVarLogDir}/$logFileName" > "$theConfigFile" + _Set_LogRotateClear_ConfigOptions_ >> "$theConfigFile" + chmod 644 "$theConfigFile" + echo "$theConfigFile" +} + +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +_Run_ClearAllLogFiles_() +{ + local logFilePath="${optVarLogDir}/messages" + local logRotateConf="${optTempDir}/ClearLog_ALL.conf" + + rm -f "$logRotateConf" + + [ -s "$logFilePath" ] && \ + echo "$logFilePath" > "$logRotateConf" + + [ ! -s "${SCRIPT_DIR}/.logs_user" ] && \ + touch "${SCRIPT_DIR}/.logs_user" + + while IFS='' read -r theLINE || [ -n "$theLINE" ] + do + if echo "$theLINE" | grep -qoF '#excluded#' + then continue + fi + logFilePath="$(echo "$theLINE" | sed 's/ *$//')" + [ -s "$logFilePath" ] && \ + echo "$logFilePath" >> "$logRotateConf" + done < "${SCRIPT_DIR}/.logs_user" + + if [ -z "$logRotateConf" ] || [ ! -s "$logRotateConf" ] + then + echo "var logClearStatus = 'ERROR';" > "$logClearStatusJS" + { + echo "Log files in [$optVarLogDir] NOT found or are EMPTY." + } > "$logClearStatusT" + return 1 + fi + + _Set_LogRotateClear_ConfigOptions_ >> "$logRotateConf" + chmod 644 "$logRotateConf" + echo "var logClearStatus = 'InProgress';" > "$logClearStatusJS" + + $logRotateCmd "$logRotateConf" > "$logRotateOutput" 2>&1 + tail -v "$logRotateOutput" > "$logClearStatusT" + [ -s "$logRotateOutput" ] && \ + cat "$logRotateOutput" > "$logRotateDaily" + echo "LogRotateClear 'ALL' was completed." >> "$logClearStatusT" + echo "var logClearStatus = 'DONE';" > "$logClearStatusJS" + rm -f "$logRotateConf" + + sleep 1 + _Get_LogRotate_FileInfoList_ +} + +##-------------------------------------## +## Added by Martinski W. [2025-Nov-28] ## +##-------------------------------------## +_Run_ClearLogFile_() +{ + rm -f "$logClearStatusJS" + + if [ $# -eq 0 ] || [ -z "$1" ] || [ ! -x "$logRotateCmd" ] + then + echo "var logClearStatus = 'ERROR';" > "$logClearStatusJS" + echo "ERROR: LogRotate is NOT available." > "$logClearStatusJS" + return 1 + fi + local logFilePath logRotateConf="" + + case "$1" in + ALL) _Run_ClearAllLogFiles_ ; return "$?" + ;; + *) logRotateConf="$(_Get_LogRotateClear_ConfigFile_ "$1")" + ;; + esac + + if [ -z "$logRotateConf" ] || [ ! -s "$logRotateConf" ] + then + logFilePath="${optVarLogDir}/$1" + echo "var logClearStatus = 'ERROR';" > "$logClearStatusJS" + { + [ ! -s "$logFilePath" ] && \ + echo "Log file [$logFilePath] NOT found or is EMPTY." + [ -n "$logRotateConf" ] && \ + echo "Check if LogRotate config file ["$logRotateConf"] exists." + } > "$logClearStatusT" + return 1 + fi + echo "var logClearStatus = 'InProgress';" > "$logClearStatusJS" + + $logRotateCmd "$logRotateConf" > "$logRotateOutput" 2>&1 + tail -v "$logRotateOutput" > "$logClearStatusT" + [ -s "$logRotateOutput" ] && \ + cat "$logRotateOutput" > "$logRotateDaily" + echo "LogRotateClear '$1' was completed." >> "$logClearStatusT" + echo "var logClearStatus = 'DONE';" > "$logClearStatusJS" + rm -f "$logRotateConf" + + sleep 1 + _Get_LogRotate_FileInfoList_ +} + ##----------------------------------------## ## Modified by Martinski W. [2025-Jun-09] ## ##----------------------------------------## @@ -818,14 +1196,14 @@ MainMenu() { Create_Dirs Create_Symlinks - printf "WebUI for %s is available at:\n${SETTING}%s${CLEARFORMAT}\n\n" "$SCRIPT_NAME" "$(Get_WebUI_URL)" - - printf "1. Customise list of logs displayed by %s\n\n" "$SCRIPT_NAME" - printf "rf. Clear user preferences for displayed logs\n\n" - printf "u. Check for updates\n" - printf "uf. Force update %s with latest version\n\n" "$SCRIPT_NAME" - printf "e. Exit %s\n\n" "$SCRIPT_NAME" - printf "z. Uninstall %s\n" "$SCRIPT_NAME" + printf " WebUI for %s is available at:\n ${SETTING}%s${CLEARFORMAT}\n\n" "$SCRIPT_NAME" "$(Get_WebUI_URL)" + + printf " 1. Customise list of logs displayed by %s\n\n" "$SCRIPT_NAME" + printf " rf. Clear user preferences for displayed logs\n\n" + printf " u. Check for updates\n" + printf " uf. Force update %s with latest version\n\n" "$SCRIPT_NAME" + printf " e. Exit %s\n\n" "$SCRIPT_NAME" + printf " z. Uninstall %s\n" "$SCRIPT_NAME" printf "\n" printf "${BOLD}########################################################${CLEARFORMAT}\n" printf "\n" @@ -928,7 +1306,7 @@ Check_Requirements() CHECKSFAILED="true" fi - if [ ! -f /opt/bin/scribe ] + if [ ! -x /opt/bin/scribe ] || [ ! -x /jffs/scripts/scribe ] then Print_Output false "Scribe is NOT installed!" "$ERR" CHECKSFAILED="true" @@ -1179,7 +1557,7 @@ then fi ##----------------------------------------## -## Modified by Martinski W. [2025-Jun-27] ## +## Modified by Martinski W. [2025-Nov-28] ## ##----------------------------------------## case "$1" in install) @@ -1193,15 +1571,27 @@ case "$1" in exit 0 ;; service_event) - if [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}config" ] + [ "$2" != "start" ] && exit 0 + if [ "$3" = "${SCRIPT_NAME}config" ] then Logs_FromSettings - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}checkupdate" ] + elif [ "$3" = "${SCRIPT_NAME}checkupdate" ] then Update_Check - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}doupdate" ] + elif [ "$3" = "${SCRIPT_NAME}doupdate" ] then Update_Version force unattended + elif echo "$3" | grep -qE "^${SCRIPT_NAME}RotateLog_.*" + then + logFileName="$(echo "$3" | cut -d'_' -f2)" + _Run_RotateLogFile_ "$logFileName" + elif echo "$3" | grep -qE "^${SCRIPT_NAME}ClearLog_.*" + then + logFileName="$(echo "$3" | cut -d'_' -f2)" + _Run_ClearLogFile_ "$logFileName" + elif echo "$3" | grep -qE "^${SCRIPT_NAME}LogFileInfoList" + then + _Get_LogRotate_FileInfoList_ fi exit 0 ;; From 43393194a11c5abb594c0d2c08e3036e19f6f72f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:31:07 +0000 Subject: [PATCH 05/14] Bump softprops/action-gh-release in the all-actions group Bumps the all-actions group with 1 update: [softprops/action-gh-release](https://github.com/softprops/action-gh-release). Updates `softprops/action-gh-release` from 2.4.2 to 2.5.0 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2.4.2...v2.5.0) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/Create-NewReleases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Create-NewReleases.yml b/.github/workflows/Create-NewReleases.yml index ecf1061..db1e121 100644 --- a/.github/workflows/Create-NewReleases.yml +++ b/.github/workflows/Create-NewReleases.yml @@ -97,7 +97,7 @@ jobs: # 7--- Publish a GitHub Release with auto-generated notes - name: Create Release with Automated Release Notes - uses: softprops/action-gh-release@v2.4.2 + uses: softprops/action-gh-release@v2.5.0 with: token: ${{ secrets.GITHUB_TOKEN }} tag_name: ${{ steps.nextver.outputs.tag }} From 670227d8a6d5e834d938dda70326ddc9f7a36a12 Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sun, 7 Dec 2025 22:02:09 -0800 Subject: [PATCH 06/14] Code Improvements - The calls to logrotate made by clicking on the "Rotate All" button will target all filtered log files, including the ones for which no individual logrotate configuration file is found. - Added a mutually exclusive lock for all calls to logrotate made from Scribe and uiScribe to prevent a possible case where simultaneous executions will attempt to rotate the same set of log files. - Installation of the latest Scribe BETA-2 development version v3.2.6_25120600 (or later) is required so that calls to logrotate from both Scribe and uiScribe can be coordinated and managed properly. --- Main_LogStatus_Content.asp | 4 +- Main_LogStatus_Content.js | 6 +- README.md | 2 +- uiScribe.sh | 453 +++++++++++++++++++++++++++---------- 4 files changed, 338 insertions(+), 127 deletions(-) diff --git a/Main_LogStatus_Content.asp b/Main_LogStatus_Content.asp index 74b45b5..0b4e1b1 100644 --- a/Main_LogStatus_Content.asp +++ b/Main_LogStatus_Content.asp @@ -25,7 +25,7 @@ p{font-weight:bolder}thead.collapsible-jquery{color:#fff;padding:0;width:100%;bo diff --git a/Main_LogStatus_Content.js b/Main_LogStatus_Content.js index dd98480..b1f0a44 100644 --- a/Main_LogStatus_Content.js +++ b/Main_LogStatus_Content.js @@ -1,5 +1,5 @@ /**----------------------------**/ -/** Last Modified: 2025-Nov-30 **/ +/** Last Modified: 2025-Dec-07 **/ /**----------------------------**/ var timeoutsenabled = true; @@ -561,8 +561,8 @@ function GetLogFileSizeInfo(theFileName) for (var indx = 0; indx < logRotate_InfoListArray.length; indx++) { - logFilePath = logRotate_InfoListArray[indx].LOG_PATH0; - logFileSize = logRotate_InfoListArray[indx].LOG_SIZE0; + logFilePath = logRotate_InfoListArray[indx].LOG_PATH; + logFileSize = logRotate_InfoListArray[indx].LOG_SIZE; logFileName = logFilePath.replace('/opt/var/log/',''); if (logFileName === theFileName) { fileSizeOK = true; break; } diff --git a/README.md b/README.md index 258f581..43cfaaa 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # uiScribe ## v1.4.10 -### Updated on 2025-Nov-30 +### Updated on 2025-Dec-07 ## About uiScribe updates the System Log page to show log files created by Scribe (syslog-ng). Requires [**Scribe**](https://github.com/cynicastic/scribe) diff --git a/uiScribe.sh b/uiScribe.sh index ad049a5..c62c120 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -13,7 +13,7 @@ ## Forked from https://github.com/jackyaz/uiScribe ## ## ## ######################################################## -# Last Modified: 2025-Nov-30 +# Last Modified: 2025-Dec-07 #------------------------------------------------------- ########### Shellcheck directives ########## @@ -30,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" readonly SCRIPT_VERSION="v1.4.10" -readonly SCRIPT_VERSTAG="25113022" +readonly SCRIPT_VERSTAG="25120720" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/${SCRIPT_NAME}.d" @@ -56,20 +56,34 @@ readonly versionMod_TAG="$SCRIPT_VERSION on $ROUTER_MODEL" readonly oneKByte=1024 readonly oneMByte=1048576 readonly oneGByte=1073741824 +readonly HOMEdir="/home/root" readonly optTempDir="/opt/tmp" readonly optVarLogDir="/opt/var/log" +readonly syslogNgStr="syslog-ng" readonly logRotateStr="logrotate" +readonly syslogNgCmd="/opt/sbin/$syslogNgStr" readonly logRotateCmd="/opt/sbin/$logRotateStr" readonly logRotateDir="/opt/etc/${logRotateStr}.d" +readonly logRotateShareDir="/opt/share/$logRotateStr" +readonly logRotateExamplesDir="${logRotateShareDir}/examples" readonly logRotateTemp="${optTempDir}/${logRotateStr}.temp" readonly logRotateDaily="${optTempDir}/${logRotateStr}.daily" readonly logRotateOutput="${optTempDir}/${logRotateStr}.out" -readonly logRotateConfig="/opt/etc/${logRotateStr}.conf" +readonly logRotateTopConf="/opt/etc/${logRotateStr}.conf" +readonly logRotateGlobalName="A01global" +readonly logRotateGlobalConf="${logRotateDir}/$logRotateGlobalName" readonly logRotateStatusT="${optTempDir}/${logRotateStr}.status" readonly logRotateStatusJS="${SCRIPT_WEB_DIR}/logRotateStatus.js" readonly logRotateInfoListJS="${SCRIPT_DIR}/logRotateInfoList.js" readonly logClearStatusT="${optTempDir}/${logRotateStr}Clear.status" readonly logClearStatusJS="${SCRIPT_WEB_DIR}/logClearStatus.js" +readonly LR_FLock_FD=513 +readonly LR_FLock_FName="/tmp/scribeLogRotate.flock" + +readonly logFilesRegExp="${optVarLogDir}/.*([.]log)?" +readonly filteredLogList="${SCRIPT_DIR}/.logs" +readonly noConfigLogList="${SCRIPT_DIR}/.noconfiglogs" +readonly userCheckLogList="${SCRIPT_DIR}/.logs_user" ### End of script variables ### @@ -159,6 +173,24 @@ Clear_Lock() return 0 } +##-------------------------------------## +## Added by Martinski W. [2025-Dec-05] ## +##-------------------------------------## +_AcquireFLock_() +{ + local opts="" + eval exec "$LR_FLock_FD>$LR_FLock_FName" + + if [ $# -eq 1 ] && [ "$1" = "nonblock" ] + then opts="-n" + fi + flock -x $opts "$LR_FLock_FD" + return "$?" +} + +_ReleaseFLock_() +{ flock -u "$LR_FLock_FD" ; } + ##----------------------------------------## ## Modified by Martinski W. [2025-Jun-09] ## ##----------------------------------------## @@ -392,44 +424,125 @@ Create_Dirs() } ##----------------------------------------## -## Modified by Martinski W. [2025-Nov-28] ## +## Modified by Martinski W. [2025-Dec-05] ## +##----------------------------------------## +_Generate_ListOf_Filtered_LogFiles_() +{ + local tmpLogList="${HOMEdir}/tempLogs_$$.txt" + + printf '' > "$filteredLogList" + if "$syslogNgCmd" --preprocess-into="$tmpLogList" + then + while read -r theLINE && [ -n "$theLINE" ] + do + logFilePath="$(echo "$theLINE" | sed -e 's/^[ ]*file("//;s/".*$//')" + if grep -qE "^${logFilePath}$" "$filteredLogList" + then continue #Avoid duplicates# + fi + echo "$logFilePath" >> "$filteredLogList" + done <> "$userCheckLogList" + fi + done < "$filteredLogList" + + while IFS='' read -r theLINE || [ -n "$theLINE" ] + do + theLogFile="$(echo "$theLINE" | cut -d' ' -f1)" + if [ "$(grep -c "^$theLogFile" "$filteredLogList")" -eq 0 ] + then #Remove# + sed -i "\\~^${theLINE}~d" "$userCheckLogList" + fi + done < "$userCheckLogList" +} + +##-------------------------------------## +## Added by Martinski W. [2025-Dec-05] ## +##-------------------------------------## +_Generate_ListOf_LogFiles_Without_Configs_() +{ + local theLogConfigExp="${logRotateDir}/*" + local configFilePath configFileOK theLogFile + + printf '' > "$noConfigLogList" + [ ! -s "$filteredLogList" ] && return 1 + + while IFS='' read -r theLINE || [ -n "$theLINE" ] + do + if echo "$theLINE" | grep -qoF '#excluded#' + then continue + fi + theLogFile="$(echo "$theLINE" | sed 's/ *$//')" + + configFileOK=false + for configFilePath in $(ls -1 $theLogConfigExp 2>/dev/null) + do + if [ ! -s "$configFilePath" ] || \ + [ "${configFilePath##*/}" = "$logRotateGlobalName" ] || \ + ! grep -qE "$logFilesRegExp" "$configFilePath" + then continue + fi + if grep -qE "$theLogFile" "$configFilePath" + then + configFileOK=true ; break + fi + done + + if ! "$configFileOK" + then echo "$theLogFile" >> "$noConfigLogList" + fi + done < "$filteredLogList" + + [ ! -s "$noConfigLogList" ] && rm -f "$noConfigLogList" +} + +##----------------------------------------## +## Modified by Martinski W. [2025-Dec-05] ## ##----------------------------------------## Create_Symlinks() { if [ -z "$(which syslog-ng)" ] then - Print_Output true "**ERROR**: syslog-ng is NOT found." "$CRIT" - touch "$SCRIPT_DIR/.logs" + Print_Output true "**ERROR**: syslog-ng is *NOT* found." "$CRIT" + touch "$filteredLogList" else - syslog-ng --preprocess-into="$SCRIPT_DIR/tmplogs.txt" && grep -A 1 "destination" "$SCRIPT_DIR/tmplogs.txt" | grep "file(\"" | grep -v "#" | grep -v "messages" | sed -e 's/file("//;s/".*$//' | awk '{$1=$1;print}' > "$SCRIPT_DIR/.logs" - rm -f "$SCRIPT_DIR/tmplogs.txt" 2>/dev/null + _Generate_ListOf_Filtered_LogFiles_ fi if [ $# -gt 0 ] && [ "$1" = "force" ] then - rm -f "$SCRIPT_DIR/.logs_user" + rm -f "$userCheckLogList" fi - if [ ! -f "$SCRIPT_DIR/.logs_user" ] + if [ ! -f "$userCheckLogList" ] then - touch "$SCRIPT_DIR/.logs_user" + touch "$userCheckLogList" fi - - while IFS='' read -r line || [ -n "$line" ] - do - if [ "$(grep -c "$line" "$SCRIPT_DIR/.logs_user")" -eq 0 ] - then - printf "%s\n" "$line" >> "$SCRIPT_DIR/.logs_user" - fi - done < "$SCRIPT_DIR/.logs" + _Update_ListOf_UserCheck_LogFiles_ rm -f "$SCRIPT_WEB_DIR/"*.htm 2>/dev/null ln -s "${optVarLogDir}/messages" "$SCRIPT_WEB_DIR/messages.htm" 2>/dev/null - ln -s "$SCRIPT_DIR/.logs_user" "$SCRIPT_WEB_DIR/logs_user.htm" 2>/dev/null + ln -s "$userCheckLogList" "$SCRIPT_WEB_DIR/logs_user.htm" 2>/dev/null - while IFS='' read -r line || [ -n "$line" ] + while IFS='' read -r theLogFile || [ -n "$theLogFile" ] do - ln -s "$line" "$SCRIPT_WEB_DIR/$(basename "$line").htm" 2>/dev/null - done < "$SCRIPT_DIR/.logs" + ln -s "$theLogFile" "$SCRIPT_WEB_DIR/$(basename "$theLogFile").htm" 2>/dev/null + done < "$filteredLogList" _Get_LogRotate_FileInfoList_ ln -s "$logRotateInfoListJS" "${SCRIPT_WEB_DIR}/logRotateInfoList.js" 2>/dev/null @@ -440,56 +553,55 @@ Create_Symlinks() } ##----------------------------------------## -## Modified by Martinski W. [2025-Nov-28] ## +## Modified by Martinski W. [2025-Dec-06] ## ##----------------------------------------## Logs_FromSettings() { SETTINGSFILE="/jffs/addons/custom_settings.txt" - LOGS_USER="$SCRIPT_DIR/.logs_user" + LOGS_USER="$userCheckLogList" + if [ -f "$SETTINGSFILE" ] then if grep -q "uiscribe_logs_enabled" "$SETTINGSFILE" then Print_Output true "Updated logs from WebUI found, merging into $LOGS_USER" "$PASS" - cp -a "$LOGS_USER" "$LOGS_USER.bak" + cp -a "$userCheckLogList" "${userCheckLogList}.bak" SETTINGVALUE="$(grep "uiscribe_logs_enabled" "$SETTINGSFILE" | cut -f2 -d' ')" sed -i "\\~uiscribe_logs_enabled~d" "$SETTINGSFILE" - syslog-ng --preprocess-into="$SCRIPT_DIR/tmplogs.txt" && grep -A 1 "destination" "$SCRIPT_DIR/tmplogs.txt" | grep "file(\"" | grep -v "#" | grep -v "messages" | sed -e 's/file("//;s/".*$//' | awk '{$1=$1;print}' > "$SCRIPT_DIR/.logs" - rm -f "$SCRIPT_DIR/tmplogs.txt" 2>/dev/null + _Generate_ListOf_Filtered_LogFiles_ + printf '' > "$userCheckLogList" - echo > "$LOGS_USER" - - comment=" #excluded#" - while IFS='' read -r line || [ -n "$line" ] + theComment=" #excluded#" + while IFS='' read -r logFile || [ -n "$logFile" ] do - if [ "$(grep -c "$line" "$LOGS_USER")" -eq 0 ] + if [ "$(grep -c "$logFile" "$userCheckLogList")" -eq 0 ] then - printf "%s%s\n" "$line" "$comment" >> "$LOGS_USER" + printf "%s%s\n" "$logFile" "$theComment" >> "$userCheckLogList" fi - done < "$SCRIPT_DIR/.logs" + done < "$filteredLogList" - for log in $(echo "$SETTINGVALUE" | sed "s/,/ /g") + for logFile in $(echo "$SETTINGVALUE" | sed "s/,/ /g") do - loglinenumber="$(grep -n "$log" "$LOGS_USER" | cut -f1 -d':')" - logline="$(sed "$loglinenumber!d" "$LOGS_USER" | awk '{$1=$1};1')" - if echo "$logline" | grep -q "#excluded" + logLineNum="$(grep -n "$logFile" "$userCheckLogList" | cut -f1 -d':')" + logFileLine="$(sed "${logLineNum}!d" "$userCheckLogList" | awk '{$1=$1};1')" + if echo "$logFileLine" | grep -q "#excluded" then - sed -i "$loglinenumber"'s/ #excluded#//' "$LOGS_USER" + sed -i "$logLineNum"'s/ #excluded#//' "$userCheckLogList" fi done - awk 'NF' "$LOGS_USER" > /tmp/uiscribe-logs - mv -f /tmp/uiscribe-logs "$LOGS_USER" + awk 'NF' "$userCheckLogList" > /tmp/uiscribe-logs + mv -f /tmp/uiscribe-logs "$userCheckLogList" rm -f "$SCRIPT_WEB_DIR/"*.htm 2>/dev/null ln -s "${optVarLogDir}/messages" "$SCRIPT_WEB_DIR/messages.htm" 2>/dev/null - ln -s "$SCRIPT_DIR/.logs_user" "$SCRIPT_WEB_DIR/logs_user.htm" 2>/dev/null + ln -s "$userCheckLogList" "$SCRIPT_WEB_DIR/logs_user.htm" 2>/dev/null - while IFS='' read -r line || [ -n "$line" ] + while IFS='' read -r logFile || [ -n "$logFile" ] do - ln -s "$line" "$SCRIPT_WEB_DIR/$(basename "$line").htm" 2>/dev/null - done < "$SCRIPT_DIR/.logs" + ln -s "$logFile" "$SCRIPT_WEB_DIR/$(basename "$logFile").htm" 2>/dev/null + done < "$filteredLogList" _Get_LogRotate_FileInfoList_ ln -s "$logRotateInfoListJS" "${SCRIPT_WEB_DIR}/logRotateInfoList.js" 2>/dev/null @@ -509,19 +621,19 @@ Generate_Log_List() ScriptHeader goback=false printf " Retrieving list of log files...\n\n" - logCount="$(wc -l < "$SCRIPT_DIR/.logs_user")" + logCount="$(wc -l < "$userCheckLogList")" COUNTER=1 until [ "$COUNTER" -gt "$logCount" ] do - logfile="$(sed "$COUNTER!d" "$SCRIPT_DIR/.logs_user" | awk '{$1=$1};1')" - printf "%2d) %s\n" "$COUNTER" "$logfile" + logfile="$(sed "$COUNTER!d" "$userCheckLogList" | awk '{$1=$1};1')" + printf "%3d) %s\n" "$COUNTER" "$logfile" COUNTER="$((COUNTER + 1))" done - printf "\n e) Go back\n" + printf "\n e) Go back\n" while true do - printf "\n${BOLD}Please select a log to toggle inclusion in %s [1-%s]:${CLEARFORMAT} " "$SCRIPT_NAME" "$logCount" + printf "\n ${BOLD}Please select a log to toggle inclusion in %s [1-%s]:${CLEARFORMAT} " "$SCRIPT_NAME" "$logCount" read -r logNum if [ "$logNum" = "e" ] @@ -540,14 +652,14 @@ Generate_Log_List() PressEnter break else - logLine="$(sed "$logNum!d" "$SCRIPT_DIR/.logs_user" | awk '{$1=$1};1')" + logLine="$(sed "$logNum!d" "$userCheckLogList" | awk '{$1=$1};1')" if echo "$logLine" | grep -q "#excluded#" then - sed -i "$logNum"'s/ #excluded#//' "$SCRIPT_DIR/.logs_user" + sed -i "$logNum"'s/ #excluded#//' "$userCheckLogList" else - sed -i "$logNum"'s/$/ #excluded#/' "$SCRIPT_DIR/.logs_user" + sed -i "$logNum"'s/$/ #excluded#/' "$userCheckLogList" fi - sed -i 's/ *$//' "$SCRIPT_DIR/.logs_user" + sed -i 's/ *$//' "$userCheckLogList" printf "\n" break fi @@ -732,16 +844,15 @@ _Get_LogRotate_ConfigFile_() then echo ; return 1 fi - local theConfigFile theConfLogExp logFileRegExp configFileOK + local theConfigFile theConfLogExp configFileOK configFileOK=false theConfLogExp="${logRotateDir}/*" - logFileRegExp="${optVarLogDir}/.*([.]log)?" for theConfigFile in $(ls -1 $theConfLogExp 2>/dev/null) do if [ ! -s "$theConfigFile" ] || \ - ! grep -qE "$logFileRegExp" "$theConfigFile" + ! grep -qE "$logFilesRegExp" "$theConfigFile" then continue fi if grep -qE "${optVarLogDir}/$1" "$theConfigFile" @@ -750,7 +861,10 @@ _Get_LogRotate_ConfigFile_() fi done - "$configFileOK" && echo "$theConfigFile" || echo + if "$configFileOK" + then echo "$theConfigFile" + else _Get_LogRotate_TempConfig_ "$1" + fi } ##-------------------------------------## @@ -758,61 +872,100 @@ _Get_LogRotate_ConfigFile_() ##-------------------------------------## _Get_LogRotate_FileInfoList_() { - local theConfLogExp theConfigFile theConfigCount - local logFileList logFileCount logFileSize logFileRegExp - + local logFileCount logFilePath logFileSize + + _AddLogFileInfo_() + { + logFileSize="$(_GetFileSize_ "$1" HRx)" + [ "$logFileSize" = "0" ] && logFileSize="0 Bytes" + printf " { LOG_PATH: '%s',\n" "$1" + printf " LOG_SIZE: '%s'\n" "$logFileSize" + printf ' }' + } + + [ ! -f "$filteredLogList" ] && touch "$filteredLogList" { - printf 'var logRotate_InfoListArray =' + printf 'var logRotate_InfoListArray =\n[\n' + _AddLogFileInfo_ "${optVarLogDir}/messages" } > "$logRotateInfoListJS" - theConfigCount=0 - theConfLogExp="${logRotateDir}/*" - logFileRegExp="${optVarLogDir}/(.*|[.]log)" - - for theConfigFile in $(ls -1 $theConfLogExp 2>/dev/null) - do - if [ ! -s "$theConfigFile" ] || \ - ! grep -qE "$logFileRegExp" "$theConfigFile" - then continue + logFileCount=1 + while IFS='' read -r logFilePath || [ -n "$logFilePath" ] + do + if grep -qE "[']${logFilePath}[']" "$logRotateInfoListJS" + then continue #Avoid duplicates# fi - logFileList="$(grep -oE "$logFileRegExp" "$theConfigFile" | awk -F' ' '{print $1}')" - [ -z "$logFileList" ] && continue - - if [ "$theConfigCount" -gt 0 ] + if [ "$logFileCount" -gt 0 ] then printf ',\n' >> "$logRotateInfoListJS" else printf '\n[\n' >> "$logRotateInfoListJS" fi - { - printf " { LR_CONFIG: '${theConfigFile}'," - } >> "$logRotateInfoListJS" + _AddLogFileInfo_ "$logFilePath" >> "$logRotateInfoListJS" + logFileCount="$((logFileCount + 1))" + done < "$filteredLogList" - logFileCount=0 - for logFPath in $logFileList - do - if [ "$logFileCount" -eq 0 ] - then printf '\n' >> "$logRotateInfoListJS" - else printf ',\n' >> "$logRotateInfoListJS" - fi - logFileSize="$(_GetFileSize_ "$logFPath" HRx)" - [ "$logFileSize" = "0" ] && logFileSize="0 Bytes" - { - printf " LOG_PATH${logFileCount}: '%s',\n" "$logFPath" - printf " LOG_SIZE${logFileCount}: '%s'" "$logFileSize" - } >> "$logRotateInfoListJS" - logFileCount="$((logFileCount + 1))" - done - { - printf '\n }' - } >> "$logRotateInfoListJS" - theConfigCount="$((theConfigCount + 1))" - done + if [ "$logFileCount" -eq 0 ] + then printf ' [];\n' >> "$logRotateInfoListJS" + else printf '\n];\n' >> "$logRotateInfoListJS" + fi +} - if [ "$theConfigCount" -eq 0 ] +##-------------------------------------## +## Added by Martinski W. [2025-Dec-05] ## +##-------------------------------------## +_DoPostRotateCleanup_() +{ + if [ ! -s "$logRotateGlobalConf" ] && \ + [ ! -s "${logRotateExamplesDir}/$logRotateGlobalName" ] + then return 1 + fi + if [ -s "${SCRIPT_DIR}/${logRotateGlobalName}.SAVED" ] then - printf ' [];\n' >> "$logRotateInfoListJS" + mv -f "${SCRIPT_DIR}/${logRotateGlobalName}.SAVED" "$logRotateGlobalConf" else - printf '\n];\n' >> "$logRotateInfoListJS" + cp -fp "${logRotateExamplesDir}/$logRotateGlobalName" "$logRotateGlobalConf" + fi +} + +##-------------------------------------## +## Added by Martinski W. [2025-Dec-05] ## +##-------------------------------------## +_RotateAllLogFiles_Preamble_() +{ + local lineNumBegin lineNumEndin + + doPostRotateCleanup=false + _Generate_ListOf_Filtered_LogFiles_ + _Update_ListOf_UserCheck_LogFiles_ + _Generate_ListOf_LogFiles_Without_Configs_ + + if [ ! -s "$noConfigLogList" ] || \ + { [ ! -s "$logRotateGlobalConf" ] && \ + [ ! -s "${logRotateExamplesDir}/$logRotateGlobalName" ] ; } + then return 1 fi + + if [ ! -s "$logRotateGlobalConf" ] || \ + grep -qE "$logFilesRegExp" "$logRotateGlobalConf" + then + if [ ! -s "${logRotateExamplesDir}/$logRotateGlobalName" ] + then return 1 + fi + cp -fp "${logRotateExamplesDir}/$logRotateGlobalName" "$logRotateGlobalConf" + chmod 644 "$logRotateGlobalConf" + fi + cp -fp "$logRotateGlobalConf" "${SCRIPT_DIR}/${logRotateGlobalName}.SAVED" + + lineNumEndin="$(grep -wn "endscript" "$logRotateGlobalConf" | cut -d':' -f1)" + lineNumBegin="$(grep -wn "postrotate" "$logRotateGlobalConf" | cut -d':' -f1)" + if [ -z "$lineNumEndin" ] || [ -z "$lineNumEndin" ] + then return 1 + fi + lineNumEndin="$((lineNumEndin + 1))" + sed -i "${lineNumEndin}i }" "$logRotateGlobalConf" + sed -i "${lineNumBegin}i {" "$logRotateGlobalConf" + lineNumBegin="$((lineNumBegin - 1))" + sed -i "${lineNumBegin}r $noConfigLogList" "$logRotateGlobalConf" + doPostRotateCleanup=true } ##-------------------------------------## @@ -828,23 +981,27 @@ _Run_RotateLogFile_() echo "ERROR: LogRotate is NOT available." > "$logRotateStatusT" return 1 fi - local logRotateConf="" + + local doPostRotateCleanup=false + local logRotateConf="$logRotateTopConf" case "$1" in - ALL) logRotateConf="$logRotateConfig" - ;; - *) logRotateConf="$(_Get_LogRotate_ConfigFile_ "$1")" - ;; + ALL) _RotateAllLogFiles_Preamble_ + ;; + *) logRotateConf="$(_Get_LogRotate_ConfigFile_ "$1")" + ;; esac if [ -z "$logRotateConf" ] || [ ! -s "$logRotateConf" ] then echo "var logRotateStatus = 'ERROR';" > "$logRotateStatusJS" { - [ ! -s "${optVarLogDir}/$1" ] && \ - echo "Log file [${optVarLogDir}/$1] NOT found or is EMPTY." + if [ "$1" != "ALL" ] && [ ! -s "${optVarLogDir}/$1" ] + then + echo "Log file [${optVarLogDir}/$1] NOT found or is EMPTY." + fi [ -n "$logRotateConf" ] && \ - echo "Check if LogRotate config file ["$logRotateConf"] exists." + echo "Check if LogRotate config file [$logRotateConf] exists." } > "$logRotateStatusT" return 1 fi @@ -858,6 +1015,7 @@ _Run_RotateLogFile_() echo "var logRotateStatus = 'DONE';" > "$logRotateStatusJS" sleep 1 + "$doPostRotateCleanup" && _DoPostRotateCleanup_ _Get_LogRotate_FileInfoList_ } @@ -885,6 +1043,52 @@ _Set_LogRotateClear_ConfigOptions_() EOF } +##-------------------------------------## +## Added by Martinski W. [2025-Dec-05] ## +##-------------------------------------## +_Set_LogRotate_ConfigOptions_() +{ + cat << 'EOF' +{ + weekly + minsize 512k + maxsize 4096k + rotate 4 + compress + delaycompress + create + dateext + dateformat -%Y%m%d%H%M + missingok + notifempty + sharedscripts + postrotate + /usr/bin/killall -HUP syslog-ng + endscript +} +EOF +} + +##-------------------------------------## +## Added by Martinski W. [2025-Dec-05] ## +##-------------------------------------## +_Get_LogRotate_TempConfig_() +{ + if [ $# -eq 0 ] || [ -z "$1" ] || \ + [ ! -s "${optVarLogDir}/$1" ] + then + echo ; return 1 + fi + local logFileName="$1" theConfigFile + theConfigFile="${optTempDir}/RotateLog_${logFileName%.*}.conf" + rm -f "$theConfigFile" + + echo "${optVarLogDir}/$logFileName" > "$theConfigFile" + _Set_LogRotate_ConfigOptions_ >> "$theConfigFile" + chmod 644 "$theConfigFile" + echo "$theConfigFile" +} + ##-------------------------------------## ## Added by Martinski W. [2025-Nov-28] ## ##-------------------------------------## @@ -918,8 +1122,7 @@ _Run_ClearAllLogFiles_() [ -s "$logFilePath" ] && \ echo "$logFilePath" > "$logRotateConf" - [ ! -s "${SCRIPT_DIR}/.logs_user" ] && \ - touch "${SCRIPT_DIR}/.logs_user" + [ ! -s "$userCheckLogList" ] && touch "$userCheckLogList" while IFS='' read -r theLINE || [ -n "$theLINE" ] do @@ -929,7 +1132,7 @@ _Run_ClearAllLogFiles_() logFilePath="$(echo "$theLINE" | sed 's/ *$//')" [ -s "$logFilePath" ] && \ echo "$logFilePath" >> "$logRotateConf" - done < "${SCRIPT_DIR}/.logs_user" + done < "$userCheckLogList" if [ -z "$logRotateConf" ] || [ ! -s "$logRotateConf" ] then @@ -986,7 +1189,7 @@ _Run_ClearLogFile_() [ ! -s "$logFilePath" ] && \ echo "Log file [$logFilePath] NOT found or is EMPTY." [ -n "$logRotateConf" ] && \ - echo "Check if LogRotate config file ["$logRotateConf"] exists." + echo "Check if LogRotate config file [$logRotateConf] exists." } > "$logClearStatusT" return 1 fi @@ -1210,7 +1413,7 @@ MainMenu() while true do - printf "Choose an option: " + printf " Choose an option: " read -r menuOption case "$menuOption" in 1) @@ -1543,7 +1746,7 @@ if [ $# -eq 0 ] || [ -z "$1" ] then NTP_Ready Entware_Ready - sed -i '/\/dev\/null/d' "$SCRIPT_DIR/.logs_user" + sed -i '/\/dev\/null/d' "$userCheckLogList" Create_Dirs Create_Symlinks Auto_Startup create 2>/dev/null @@ -1557,7 +1760,7 @@ then fi ##----------------------------------------## -## Modified by Martinski W. [2025-Nov-28] ## +## Modified by Martinski W. [2025-Dec-05] ## ##----------------------------------------## case "$1" in install) @@ -1584,11 +1787,19 @@ case "$1" in elif echo "$3" | grep -qE "^${SCRIPT_NAME}RotateLog_.*" then logFileName="$(echo "$3" | cut -d'_' -f2)" - _Run_RotateLogFile_ "$logFileName" + if _AcquireFLock_ nonblock + then + _Run_RotateLogFile_ "$logFileName" + _ReleaseFLock_ + fi elif echo "$3" | grep -qE "^${SCRIPT_NAME}ClearLog_.*" then logFileName="$(echo "$3" | cut -d'_' -f2)" - _Run_ClearLogFile_ "$logFileName" + if _AcquireFLock_ nonblock + then + _Run_ClearLogFile_ "$logFileName" + _ReleaseFLock_ + fi elif echo "$3" | grep -qE "^${SCRIPT_NAME}LogFileInfoList" then _Get_LogRotate_FileInfoList_ @@ -1604,7 +1815,7 @@ case "$1" in exit 0 ;; setversion) - sed -i '/\/dev\/null/d' "$SCRIPT_DIR/.logs_user" + sed -i '/\/dev\/null/d' "$userCheckLogList" Create_Dirs Create_Symlinks Auto_Startup create 2>/dev/null @@ -1615,7 +1826,7 @@ case "$1" in exit 0 ;; postupdate) - sed -i '/\/dev\/null/d' "$SCRIPT_DIR/.logs_user" + sed -i '/\/dev\/null/d' "$userCheckLogList" Create_Dirs Create_Symlinks Auto_Startup create 2>/dev/null From 5f9f30146d135731fbb43c37d1d87928fa20ab0c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:19:50 +0000 Subject: [PATCH 07/14] Bump actions/checkout from 6.0.0 to 6.0.1 in the all-actions group Bumps the all-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 6.0.0 to 6.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6.0.0...v6.0.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/Create-NewReleases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Create-NewReleases.yml b/.github/workflows/Create-NewReleases.yml index db1e121..0b13a90 100644 --- a/.github/workflows/Create-NewReleases.yml +++ b/.github/workflows/Create-NewReleases.yml @@ -19,7 +19,7 @@ jobs: steps: # 1--- Check out master so we tag the exact merge commit - name: Checkout source code - uses: actions/checkout@v6.0.0 + uses: actions/checkout@v6.0.1 with: fetch-depth: 0 ref: 'master' From fb325559c32ba4413adccd844cef250060785ebc Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sat, 13 Dec 2025 02:19:47 -0800 Subject: [PATCH 08/14] Functional Improvements Added calls to generate list of filtered & user-check files when loading the WebUI page. --- README.md | 2 +- uiScribe.sh | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 43cfaaa..b6282e8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # uiScribe ## v1.4.10 -### Updated on 2025-Dec-07 +### Updated on 2025-Dec-13 ## About uiScribe updates the System Log page to show log files created by Scribe (syslog-ng). Requires [**Scribe**](https://github.com/cynicastic/scribe) diff --git a/uiScribe.sh b/uiScribe.sh index c62c120..22b5e3a 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -13,7 +13,7 @@ ## Forked from https://github.com/jackyaz/uiScribe ## ## ## ######################################################## -# Last Modified: 2025-Dec-07 +# Last Modified: 2025-Dec-13 #------------------------------------------------------- ########### Shellcheck directives ########## @@ -30,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" readonly SCRIPT_VERSION="v1.4.10" -readonly SCRIPT_VERSTAG="25120720" +readonly SCRIPT_VERSTAG="25121300" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/${SCRIPT_NAME}.d" @@ -1760,7 +1760,7 @@ then fi ##----------------------------------------## -## Modified by Martinski W. [2025-Dec-05] ## +## Modified by Martinski W. [2025-Dec-13] ## ##----------------------------------------## case "$1" in install) @@ -1802,7 +1802,9 @@ case "$1" in fi elif echo "$3" | grep -qE "^${SCRIPT_NAME}LogFileInfoList" then + _Generate_ListOf_Filtered_LogFiles_ _Get_LogRotate_FileInfoList_ + _Update_ListOf_UserCheck_LogFiles_ fi exit 0 ;; From b10bbe8274af3728c70674f6448ff5b3bb5d8f09 Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Wed, 17 Dec 2025 00:21:51 -0800 Subject: [PATCH 09/14] Code Improvements - Improved code that generated the list of filtered log files based on the syslog-ng configuration files. - Improved code that rotates an individual log file on demand so that even if the logfile does not have a corresponding logrotate configuration file, it will still be rotated using default settings. --- README.md | 2 +- uiScribe.sh | 51 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index b6282e8..2836a7e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # uiScribe ## v1.4.10 -### Updated on 2025-Dec-13 +### Updated on 2025-Dec-16 ## About uiScribe updates the System Log page to show log files created by Scribe (syslog-ng). Requires [**Scribe**](https://github.com/cynicastic/scribe) diff --git a/uiScribe.sh b/uiScribe.sh index 22b5e3a..48cadc3 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -13,7 +13,7 @@ ## Forked from https://github.com/jackyaz/uiScribe ## ## ## ######################################################## -# Last Modified: 2025-Dec-13 +# Last Modified: 2025-Dec-16 #------------------------------------------------------- ########### Shellcheck directives ########## @@ -30,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" readonly SCRIPT_VERSION="v1.4.10" -readonly SCRIPT_VERSTAG="25121300" +readonly SCRIPT_VERSTAG="25121622" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/${SCRIPT_NAME}.d" @@ -424,27 +424,35 @@ Create_Dirs() } ##----------------------------------------## -## Modified by Martinski W. [2025-Dec-05] ## +## Modified by Martinski W. [2025-Dec-13] ## ##----------------------------------------## _Generate_ListOf_Filtered_LogFiles_() { - local tmpLogList="${HOMEdir}/tempLogs_$$.txt" + local tmpSysLogList="${HOMEdir}/tempSysLogList_$$.txt" + local tmpFilterList="${HOMEdir}/tempFltLogList_$$.txt" + + printf '' > "$tmpFilterList" + [ ! -f "$filteredLogList" ] && printf '' > "$filteredLogList" - printf '' > "$filteredLogList" - if "$syslogNgCmd" --preprocess-into="$tmpLogList" + if "$syslogNgCmd" --preprocess-into="$tmpSysLogList" then while read -r theLINE && [ -n "$theLINE" ] do logFilePath="$(echo "$theLINE" | sed -e 's/^[ ]*file("//;s/".*$//')" - if grep -qE "^${logFilePath}$" "$filteredLogList" + if grep -qE "^${logFilePath}$" "$tmpFilterList" then continue #Avoid duplicates# fi - echo "$logFilePath" >> "$filteredLogList" + echo "$logFilePath" >> "$tmpFilterList" done </dev/null 2>&1 + then + mv -f "$tmpFilterList" "$filteredLogList" + fi + rm -f "$tmpSysLogList" "$tmpFilterList" } ##-------------------------------------## @@ -955,9 +963,9 @@ _RotateAllLogFiles_Preamble_() fi cp -fp "$logRotateGlobalConf" "${SCRIPT_DIR}/${logRotateGlobalName}.SAVED" - lineNumEndin="$(grep -wn "endscript" "$logRotateGlobalConf" | cut -d':' -f1)" - lineNumBegin="$(grep -wn "postrotate" "$logRotateGlobalConf" | cut -d':' -f1)" - if [ -z "$lineNumEndin" ] || [ -z "$lineNumEndin" ] + lineNumEndin="$(grep -wn -m1 "^endscript" "$logRotateGlobalConf" | cut -d':' -f1)" + lineNumBegin="$(grep -wn -m1 "^postrotate" "$logRotateGlobalConf" | cut -d':' -f1)" + if [ -z "$lineNumBegin" ] || [ -z "$lineNumEndin" ] then return 1 fi lineNumEndin="$((lineNumEndin + 1))" @@ -1026,9 +1034,10 @@ _Set_LogRotateClear_ConfigOptions_() { cat << 'EOF' { - hourly + daily size 0k - rotate 9 + rotate 25 + maxage 25 compress create dateext @@ -1054,6 +1063,7 @@ _Set_LogRotate_ConfigOptions_() minsize 512k maxsize 4096k rotate 4 + maxage 30 compress delaycompress create @@ -1740,13 +1750,16 @@ else SCRIPT_VERS_INFO="[$versionDev_TAG]" fi ##----------------------------------------## -## Modified by Martinski W. [2025-Jun-15] ## +## Modified by Martinski W. [2025-Dec-13] ## ##----------------------------------------## if [ $# -eq 0 ] || [ -z "$1" ] then NTP_Ready Entware_Ready - sed -i '/\/dev\/null/d' "$userCheckLogList" + if grep -qF '/dev/null' "$userCheckLogList" + then + sed -i '/\/dev\/null/d' "$userCheckLogList" + fi Create_Dirs Create_Symlinks Auto_Startup create 2>/dev/null @@ -1786,7 +1799,7 @@ case "$1" in Update_Version force unattended elif echo "$3" | grep -qE "^${SCRIPT_NAME}RotateLog_.*" then - logFileName="$(echo "$3" | cut -d'_' -f2)" + logFileName="$(echo "$3" | cut -d'_' -f2-)" if _AcquireFLock_ nonblock then _Run_RotateLogFile_ "$logFileName" @@ -1794,7 +1807,7 @@ case "$1" in fi elif echo "$3" | grep -qE "^${SCRIPT_NAME}ClearLog_.*" then - logFileName="$(echo "$3" | cut -d'_' -f2)" + logFileName="$(echo "$3" | cut -d'_' -f2-)" if _AcquireFLock_ nonblock then _Run_ClearLogFile_ "$logFileName" From a92b51b0cca491042e49f2f266c3e61937166b5f Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Wed, 17 Dec 2025 01:26:20 -0800 Subject: [PATCH 10/14] Update uiScribe.sh Fine-Tuning Code. --- uiScribe.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uiScribe.sh b/uiScribe.sh index 48cadc3..9282dc2 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -30,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" readonly SCRIPT_VERSION="v1.4.10" -readonly SCRIPT_VERSTAG="25121622" +readonly SCRIPT_VERSTAG="25121623" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/${SCRIPT_NAME}.d" @@ -428,8 +428,8 @@ Create_Dirs() ##----------------------------------------## _Generate_ListOf_Filtered_LogFiles_() { - local tmpSysLogList="${HOMEdir}/tempSysLogList_$$.txt" - local tmpFilterList="${HOMEdir}/tempFltLogList_$$.txt" + local tmpSysLogList="${HOMEdir}/${SCRIPT_NAME}_tempSysLogList_$$.txt" + local tmpFilterList="${HOMEdir}/${SCRIPT_NAME}_tempFltLogList_$$.txt" printf '' > "$tmpFilterList" [ ! -f "$filteredLogList" ] && printf '' > "$filteredLogList" From 6a20552b4799133dfd2a2398e4f20f22b2ed5e4c Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sat, 20 Dec 2025 00:28:54 -0800 Subject: [PATCH 11/14] Functional Improvement - Improved the way log files without a corresponding logrotate configuration file are rotated. --- README.md | 2 +- uiScribe.sh | 110 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 79 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 2836a7e..f6a6de0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # uiScribe ## v1.4.10 -### Updated on 2025-Dec-16 +### Updated on 2025-Dec-19 ## About uiScribe updates the System Log page to show log files created by Scribe (syslog-ng). Requires [**Scribe**](https://github.com/cynicastic/scribe) diff --git a/uiScribe.sh b/uiScribe.sh index 9282dc2..e07021c 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -13,7 +13,7 @@ ## Forked from https://github.com/jackyaz/uiScribe ## ## ## ######################################################## -# Last Modified: 2025-Dec-16 +# Last Modified: 2025-Dec-19 #------------------------------------------------------- ########### Shellcheck directives ########## @@ -30,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" readonly SCRIPT_VERSION="v1.4.10" -readonly SCRIPT_VERSTAG="25121623" +readonly SCRIPT_VERSTAG="25121920" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/${SCRIPT_NAME}.d" @@ -543,18 +543,19 @@ Create_Symlinks() fi _Update_ListOf_UserCheck_LogFiles_ - rm -f "$SCRIPT_WEB_DIR/"*.htm 2>/dev/null - ln -s "${optVarLogDir}/messages" "$SCRIPT_WEB_DIR/messages.htm" 2>/dev/null ln -s "$userCheckLogList" "$SCRIPT_WEB_DIR/logs_user.htm" 2>/dev/null + ln -s "${optVarLogDir}/messages" "$SCRIPT_WEB_DIR/messages.htm" 2>/dev/null + + _Get_LogRotate_FileInfoList_ + ln -s "$logRotateInfoListJS" "${SCRIPT_WEB_DIR}/logRotateInfoList.js" 2>/dev/null + + rm -f "$SCRIPT_WEB_DIR/"*.log.htm 2>/dev/null while IFS='' read -r theLogFile || [ -n "$theLogFile" ] do ln -s "$theLogFile" "$SCRIPT_WEB_DIR/$(basename "$theLogFile").htm" 2>/dev/null done < "$filteredLogList" - _Get_LogRotate_FileInfoList_ - ln -s "$logRotateInfoListJS" "${SCRIPT_WEB_DIR}/logRotateInfoList.js" 2>/dev/null - if [ ! -d "$SHARED_WEB_DIR" ]; then ln -s "$SHARED_DIR" "$SHARED_WEB_DIR" 2>/dev/null fi @@ -869,9 +870,9 @@ _Get_LogRotate_ConfigFile_() fi done - if "$configFileOK" - then echo "$theConfigFile" - else _Get_LogRotate_TempConfig_ "$1" + if ! "$configFileOK" + then _Get_LogRotate_TempConfig_ "$1" + else _PrependGlobalDirectives_ "$theConfigFile" fi } @@ -939,7 +940,8 @@ _DoPostRotateCleanup_() ##-------------------------------------## _RotateAllLogFiles_Preamble_() { - local lineNumBegin lineNumEndin + local lineNumInsert + local tmpLogRotateAction="${HOMEdir}/${SCRIPT_NAME}_tempLogRotateAction_$$.txt" doPostRotateCleanup=false _Generate_ListOf_Filtered_LogFiles_ @@ -963,16 +965,22 @@ _RotateAllLogFiles_Preamble_() fi cp -fp "$logRotateGlobalConf" "${SCRIPT_DIR}/${logRotateGlobalName}.SAVED" - lineNumEndin="$(grep -wn -m1 "^endscript" "$logRotateGlobalConf" | cut -d':' -f1)" - lineNumBegin="$(grep -wn -m1 "^postrotate" "$logRotateGlobalConf" | cut -d':' -f1)" - if [ -z "$lineNumBegin" ] || [ -z "$lineNumEndin" ] - then return 1 - fi - lineNumEndin="$((lineNumEndin + 1))" - sed -i "${lineNumEndin}i }" "$logRotateGlobalConf" - sed -i "${lineNumBegin}i {" "$logRotateGlobalConf" - lineNumBegin="$((lineNumBegin - 1))" - sed -i "${lineNumBegin}r $noConfigLogList" "$logRotateGlobalConf" + lineNumInsert="$(grep -wn -m1 "^endscript" "$logRotateGlobalConf" | cut -d':' -f1)" + [ -z "$lineNumInsert" ] && return 1 + lineNumInsert="$((lineNumInsert + 1))" + + cat "$noConfigLogList" > "$tmpLogRotateAction" + cat <> "$tmpLogRotateAction" +{ + lastaction + /usr/bin/killall -HUP syslog-ng + endscript +} + +EOF + + sed -i "${lineNumInsert}r $tmpLogRotateAction" "$logRotateGlobalConf" + rm -f "$tmpLogRotateAction" doPostRotateCleanup=true } @@ -1024,6 +1032,10 @@ _Run_RotateLogFile_() sleep 1 "$doPostRotateCleanup" && _DoPostRotateCleanup_ + if echo "$logRotateConf" | grep -qE "^${optTempDir}/RotateLog_.*" + then + rm -f "$logRotateConf" + fi _Get_LogRotate_FileInfoList_ } @@ -1089,14 +1101,44 @@ _Get_LogRotate_TempConfig_() then echo ; return 1 fi - local logFileName="$1" theConfigFile - theConfigFile="${optTempDir}/RotateLog_${logFileName%.*}.conf" - rm -f "$theConfigFile" + local logFileName="$1" configFPath + configFPath="${optTempDir}/RotateLog_${logFileName%.*}.conf" + rm -f "$configFPath" + + echo "${optVarLogDir}/$logFileName" > "$configFPath" + _Set_LogRotate_ConfigOptions_ >> "$configFPath" + chmod 644 "$configFPath" + echo "$configFPath" +} - echo "${optVarLogDir}/$logFileName" > "$theConfigFile" - _Set_LogRotate_ConfigOptions_ >> "$theConfigFile" - chmod 644 "$theConfigFile" - echo "$theConfigFile" +##-------------------------------------## +## Added by Martinski W. [2025-Dec-18] ## +##-------------------------------------## +_PrependGlobalDirectives_() +{ + if [ $# -eq 0 ] || [ -z "$1" ] || [ ! -s "$1" ] + then echo ; return 1 + fi + local configFPath + + if [ ! -s "$logRotateGlobalConf" ] || \ + grep -qE "$logFilesRegExp" "$logRotateGlobalConf" + then + if [ ! -s "${logRotateExamplesDir}/$logRotateGlobalName" ] + then echo "$1" ; return 1 + fi + cp -fp "${logRotateExamplesDir}/$logRotateGlobalName" "$logRotateGlobalConf" + chmod 644 "$logRotateGlobalConf" + fi + + configFPath="${optTempDir}/RotateLog_${1##*/}.conf" + rm -f "$configFPath" + + cat "$logRotateGlobalConf" > "$configFPath" + sed -i '/^#EOF#/d' "$configFPath" + cat "$1" >> "$configFPath" + chmod 644 "$configFPath" + echo "$configFPath" } ##-------------------------------------## @@ -1773,7 +1815,7 @@ then fi ##----------------------------------------## -## Modified by Martinski W. [2025-Dec-13] ## +## Modified by Martinski W. [2025-Dec-19] ## ##----------------------------------------## case "$1" in install) @@ -1804,6 +1846,9 @@ case "$1" in then _Run_RotateLogFile_ "$logFileName" _ReleaseFLock_ + else + echo "var logRotateStatus = 'ERROR';" > "$logRotateStatusJS" + echo "ERROR: Unable to acquire lock to run logrotate." > "$logRotateStatusT" fi elif echo "$3" | grep -qE "^${SCRIPT_NAME}ClearLog_.*" then @@ -1812,12 +1857,13 @@ case "$1" in then _Run_ClearLogFile_ "$logFileName" _ReleaseFLock_ + else + echo "var logRotateStatus = 'ERROR';" > "$logRotateStatusJS" + echo "ERROR: Unable to acquire lock to run logrotate." > "$logRotateStatusT" fi elif echo "$3" | grep -qE "^${SCRIPT_NAME}LogFileInfoList" then - _Generate_ListOf_Filtered_LogFiles_ - _Get_LogRotate_FileInfoList_ - _Update_ListOf_UserCheck_LogFiles_ + Create_Symlinks fi exit 0 ;; From 7b211c57d6a007c2544119196515efd3396ff791 Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sun, 21 Dec 2025 01:38:06 -0800 Subject: [PATCH 12/14] Modified logrotate Directive Modified logrotate directive for compression. --- README.md | 2 +- uiScribe.sh | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f6a6de0..e53ad45 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # uiScribe ## v1.4.10 -### Updated on 2025-Dec-19 +### Updated on 2025-Dec-21 ## About uiScribe updates the System Log page to show log files created by Scribe (syslog-ng). Requires [**Scribe**](https://github.com/cynicastic/scribe) diff --git a/uiScribe.sh b/uiScribe.sh index e07021c..d8d09be 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -13,7 +13,7 @@ ## Forked from https://github.com/jackyaz/uiScribe ## ## ## ######################################################## -# Last Modified: 2025-Dec-19 +# Last Modified: 2025-Dec-20 #------------------------------------------------------- ########### Shellcheck directives ########## @@ -30,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" readonly SCRIPT_VERSION="v1.4.10" -readonly SCRIPT_VERSTAG="25121920" +readonly SCRIPT_VERSTAG="25122023" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/${SCRIPT_NAME}.d" @@ -1050,7 +1050,7 @@ _Set_LogRotateClear_ConfigOptions_() size 0k rotate 25 maxage 25 - compress + delaycompress create dateext dateformat -%Y%m%d%H%M%S @@ -1076,7 +1076,6 @@ _Set_LogRotate_ConfigOptions_() maxsize 4096k rotate 4 maxage 30 - compress delaycompress create dateext From e3b0768bb45f61095ca8cf266c46685a9074a1bb Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sun, 21 Dec 2025 22:43:30 -0800 Subject: [PATCH 13/14] Fine-Tuning Log Rotation Directive Fine-tuning directive to run script after a log file has been rotated. --- uiScribe.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uiScribe.sh b/uiScribe.sh index d8d09be..c1842a0 100644 --- a/uiScribe.sh +++ b/uiScribe.sh @@ -13,7 +13,7 @@ ## Forked from https://github.com/jackyaz/uiScribe ## ## ## ######################################################## -# Last Modified: 2025-Dec-20 +# Last Modified: 2025-Dec-21 #------------------------------------------------------- ########### Shellcheck directives ########## @@ -30,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="uiScribe" readonly SCRIPT_VERSION="v1.4.10" -readonly SCRIPT_VERSTAG="25122023" +readonly SCRIPT_VERSTAG="25122122" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://raw.githubusercontent.com/AMTM-OSR/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/${SCRIPT_NAME}.d" @@ -972,7 +972,7 @@ _RotateAllLogFiles_Preamble_() cat "$noConfigLogList" > "$tmpLogRotateAction" cat <> "$tmpLogRotateAction" { - lastaction + postrotate /usr/bin/killall -HUP syslog-ng endscript } From d09e099e0ae45c80dc43391d81d60f21672b0ba4 Mon Sep 17 00:00:00 2001 From: Martinski4GitHub <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:19:43 -0800 Subject: [PATCH 14/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e53ad45..f81c742 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # uiScribe ## v1.4.10 -### Updated on 2025-Dec-21 +### Updated on 2025-Dec-22 ## About uiScribe updates the System Log page to show log files created by Scribe (syslog-ng). Requires [**Scribe**](https://github.com/cynicastic/scribe)