🛠Maintenance refactor

This commit is contained in:
jokob-sk
2024-06-29 14:39:12 +10:00
parent 709408ca2a
commit 08b163ebe4
26 changed files with 370 additions and 232 deletions

View File

@@ -43,12 +43,17 @@ RUN apk update --no-cache \
&& apk add --no-cache curl arp-scan iproute2 iproute2-ss nmap nmap-scripts traceroute net-tools net-snmp-tools bind-tools awake ca-certificates \ && apk add --no-cache curl arp-scan iproute2 iproute2-ss nmap nmap-scripts traceroute net-tools net-snmp-tools bind-tools awake ca-certificates \
&& apk add --no-cache sqlite php83 php83-fpm php83-cgi php83-curl php83-sqlite3 php83-session \ && apk add --no-cache sqlite php83 php83-fpm php83-cgi php83-curl php83-sqlite3 php83-session \
&& apk add --no-cache python3 nginx \ && apk add --no-cache python3 nginx \
&& apk add --no-cache dcron \
&& ln -s /usr/bin/awake /usr/bin/wakeonlan \ && ln -s /usr/bin/awake /usr/bin/wakeonlan \
&& bash -c "install -d -m 750 -o nginx -g www-data ${INSTALL_DIR} ${INSTALL_DIR}" \ && bash -c "install -d -m 750 -o nginx -g www-data ${INSTALL_DIR} ${INSTALL_DIR}" \
&& rm -f /etc/nginx/http.d/default.conf && rm -f /etc/nginx/http.d/default.conf
COPY --from=builder --chown=nginx:www-data ${INSTALL_DIR}/ ${INSTALL_DIR}/ COPY --from=builder --chown=nginx:www-data ${INSTALL_DIR}/ ${INSTALL_DIR}/
# Add crontab file
COPY install/crontab /etc/crontabs/root
# Start all required services
RUN ${INSTALL_DIR}/dockerfiles/pre-setup.sh RUN ${INSTALL_DIR}/dockerfiles/pre-setup.sh
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=2 \ HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=2 \

13
back/cron_script.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
export INSTALL_DIR=/app
LOG_FILE="${INSTALL_DIR}/front/log/execution_queue.log"
# Check if there are any entries with cron_restart_backend
if grep -q "cron_restart_backend" "$LOG_FILE"; then
# Kill all python processes and restart the server
pkill -f "python " && (python ${INSTALL_DIR}/server > /dev/null 2>&1 &) && echo 'done'
# Remove all lines containing cron_restart_backend from the log file
sed -i '/cron_restart_backend/d' "$LOG_FILE"
fi

View File

@@ -38,4 +38,6 @@ touch /etc/s6-overlay/s6-rc.d/user/contents.d/{SetupOneshot,php-fpm,nginx,$APP_N
touch /etc/s6-overlay/s6-rc.d/nginx/dependencies.d/php-fpm touch /etc/s6-overlay/s6-rc.d/nginx/dependencies.d/php-fpm
touch /etc/s6-overlay/s6-rc.d/$APP_NAME/dependencies.d/nginx touch /etc/s6-overlay/s6-rc.d/$APP_NAME/dependencies.d/nginx
rm -f $0 rm -f $0

View File

@@ -109,6 +109,10 @@ if [ ! -f "${INSTALL_DIR}/front/buildtimestamp.txt" ]; then
chown nginx:www-data "${INSTALL_DIR}/front/buildtimestamp.txt" chown nginx:www-data "${INSTALL_DIR}/front/buildtimestamp.txt"
fi fi
# Start crond service in the background
echo "[INSTALL] Starting crond service..."
crond -f -d 8 > /dev/null 2>&1 &
echo -e " echo -e "
[ENV] PATH is ${PATH} [ENV] PATH is ${PATH}
[ENV] PORT is ${PORT} [ENV] PORT is ${PORT}

View File

@@ -27,11 +27,17 @@
font-family: 'Courier New', monospace; font-family: 'Courier New', monospace;
} }
.logs-row textarea
{
width: 100%;
}
.logs-row button{
margin: 2px;
}
.logs-row .logs-row
{ {
align-content: center; align-content: center;
width: 100%; width: 100%;
display: grid;
margin: 5px; margin: 5px;
} }
.logs-size .logs-size
@@ -52,8 +58,7 @@
} }
.log-file .log-file
{ {
width: 145px;
display: inline-grid;
font-size: 20px; font-size: 20px;
} }
.log-purge .log-purge

View File

@@ -336,6 +336,7 @@ function getDevicesTotals(devicesData) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Render the info boxes/tiles on top
function renderInfoboxes(customData) { function renderInfoboxes(customData) {
$.ajax({ $.ajax({
url: 'php/components/tile_cards.php', // PHP script URL url: 'php/components/tile_cards.php', // PHP script URL

View File

@@ -147,19 +147,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_det" href="#collapse301">
<?= lang('HelpFAQ_Cat_Detail_301_head_a');?> "<?= lang('DevDetail_EveandAl_ScanCycle');?>" <?= lang('HelpFAQ_Cat_Detail_301_head_b');?></a>
</h4>
</div>
<div id="collapse301" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_Detail_301_text');?>
</div>
</div>
</div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h4 class="panel-title"> <h4 class="panel-title">

View File

@@ -412,58 +412,6 @@ function filterRows(inputText) {
// -----------------------------------------------------------------------------
// handling events on the backend initiated by the front end START
// -----------------------------------------------------------------------------
modalEventStatusId = 'modal-message-front-event'
// --------------------------------------------------------
// Calls a backend function to add a front-end event (specified by the attributes 'data-myevent' and 'data-myparam-plugin' on the passed element) to an execution queue
function addToExecutionQueue(element)
{
// value has to be in format event|param. e.g. run|ARPSCAN
action = `${getGuid()}|${$(element).attr('data-myevent')}|${$(element).attr('data-myparam-plugin')}`
$.ajax({
method: "POST",
url: "php/server/util.php",
data: { function: "addToExecutionQueue", action: action },
success: function(data, textStatus) {
// showModalOk ('Result', data );
// show message
showModalOk(getString("general_event_title"), `${getString("general_event_description")} <br/> <br/> <code id='${modalEventStatusId}'></code>`);
updateModalState()
}
})
}
// --------------------------------------------------------
// Updating the execution queue in in modal pop-up
function updateModalState() {
setTimeout(function() {
// Fetch the content from the log file using an AJAX request
$.ajax({
url: '/log/execution_queue.log',
type: 'GET',
success: function(data) {
// Update the content of the HTML element (e.g., a div with id 'logContent')
$('#'+modalEventStatusId).html(data);
updateModalState();
},
error: function() {
// Handle error, such as the file not being found
$('#logContent').html('Error: Log file not found.');
}
});
}, 2000);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// handling events on the backend initiated by the front end END // handling events on the backend initiated by the front end END
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@@ -306,6 +306,57 @@ function getCellValue(row, index) {
return $(row).children('td').eq(index).text(); return $(row).children('td').eq(index).text();
} }
// -----------------------------------------------------------------------------
// handling events on the backend initiated by the front end START
// -----------------------------------------------------------------------------
modalEventStatusId = 'modal-message-front-event'
// --------------------------------------------------------
// Calls a backend function to add a front-end event (specified by the attributes 'data-myevent' and 'data-myparam-plugin' on the passed element) to an execution queue
function addToExecutionQueue(element)
{
// value has to be in format event|param. e.g. run|ARPSCAN
action = `${getGuid()}|${$(element).attr('data-myevent')}|${$(element).attr('data-myparam-plugin')}`
$.ajax({
method: "POST",
url: "php/server/util.php",
data: { function: "addToExecutionQueue", action: action },
success: function(data, textStatus) {
// showModalOk ('Result', data );
// show message
showModalOk(getString("general_event_title"), `${getString("general_event_description")} <br/> <br/> <code id='${modalEventStatusId}'></code>`);
updateModalState()
}
})
}
// --------------------------------------------------------
// Updating the execution queue in in modal pop-up
function updateModalState() {
setTimeout(function() {
// Fetch the content from the log file using an AJAX request
$.ajax({
url: '/log/execution_queue.log',
type: 'GET',
success: function(data) {
// Update the content of the HTML element (e.g., a div with id 'logContent')
$('#'+modalEventStatusId).html(data);
updateModalState();
},
error: function() {
// Handle error, such as the file not being found
$('#logContent').html('Error: Log file not found.');
}
});
}, 2000);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// initialize // initialize

View File

@@ -405,112 +405,8 @@ $db->close();
<!-- ---------------------------Logging-------------------------------------------- --> <!-- ---------------------------Logging-------------------------------------------- -->
<div class="tab-pane" id="tab_Logging"> <div class="tab-pane" id="tab_Logging">
<div class="db_info_table"> <div class="db_info_table">
<div class="log-area box box-solid box-primary">
<div class="row logs-row">
<textarea id="app_log" class="logs" cols="70" rows="10" wrap='off' readonly >
<?php
if(filesize("./log/app.log") > 2000000)
{
echo file_get_contents( "./log/app.log", false, null, -2000000);
}
else{
echo file_get_contents( "./log/app.log" );
}
?> <div id="logsPlc"></div>
</textarea>
</div>
<div class="row logs-row" >
<div>
<div class="log-file">app.log <div class="logs-size"><?php echo number_format((filesize("./log/app.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/app.log" target="_blank"><i class="fa fa-download"></i> </a></span>
</div></div>
<button class="btn btn-primary col-sm-2 col-xs-2" onclick="restartBackend()">Not working: Restart Backend</button>
<div class="log-purge">
<button class="btn btn-primary " onclick="logManage('app.log','cleanLog')"><?= lang('Gen_Purge');?></button>
</div>
</div>
</div>
</div>
<div class="log-area box box-solid box-primary">
<div class="row logs-row">
<textarea id="app_front_log" class="logs" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "./log/app_front.log" ); ?>
</textarea>
</div>
<div class="row logs-row" >
<div>
<div class="log-file">app_front.log<div class="logs-size"><?php echo number_format((filesize("./log/app_front.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/app_front.log"><i class="fa fa-download"></i> </a></span>
</div></div>
<div class="log-purge">
<button class="btn btn-primary" onclick="logManage('app_front.log','cleanLog')"><?= lang('Gen_Purge');?></button>
</div>
</div>
</div>
</div>
<div class="log-area box box-solid box-primary">
<div class="row logs-row">
<textarea id="app_php_log" class="logs" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "./log/app.php_errors.log" ); ?>
</textarea>
</div>
<div class="row logs-row" >
<div>
<div class="log-file">app.php_errors.log<div class="logs-size"><?php echo number_format((filesize("./log/app.php_errors.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/app.php_errors.log"><i class="fa fa-download"></i> </a></span>
</div></div>
<div class="log-purge">
<button class="btn btn-primary" onclick="logManage('app.php_errors.log','cleanLog')"><?= lang('Gen_Purge');?></button>
</div>
</div>
</div>
</div>
<div class="log-area box box-solid box-primary ">
<div class="row logs-row">
<textarea id="nginx_error_log" class="logs logs-small" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "/var/log/nginx/error.log" ); ?>
</textarea>
</div>
<div class="row logs-row" >
<div>
<div class="log-file" title="/var/log/nginx/error.log">nginx/error.log</div>
<span class="span-padding"><a href="/var/log/nginx/error.log"><i class="fa fa-download"></i> </a></span>
</div>
</div>
</div>
<div class="log-area box box-solid box-primary">
<div class="row logs-row">
<textarea id="stdout_log" class="logs logs-small" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "./log/stdout.log" ); ?>
</textarea>
</div>
<div class="row logs-row" >
<div>
<div class="log-file">stdout.log<div class="logs-size"><?php echo number_format((filesize("./log/stdout.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/stdout.log"><i class="fa fa-download"></i> </a></span>
</div></div>
<div class="log-purge">
<button class="btn btn-primary" onclick="logManage('stdout.log','cleanLog')"><?= lang('Gen_Purge');?></button>
</div>
</div>
</div>
</div>
<div class="log-area box box-solid box-primary">
<div class="row logs-row">
<textarea id="stderr_log" class="logs logs-small" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "./log/stderr.log" ); ?>
</textarea>
</div>
<div class="row logs-row" >
<div>
<div class="log-file">stderr.log<div class="logs-size"><?php echo number_format((filesize("./log/stderr.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/stderr.log"><i class="fa fa-download"></i> </a></span>
</div></div>
<div class="log-purge">
<button class="btn btn-primary" onclick="logManage('stderr.log','cleanLog')"><?= lang('Gen_Purge');?></button>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
@@ -566,12 +462,14 @@ var selectedTab = 'tab_Settings_id';
initializeTabs(); initializeTabs();
// -----------------------------------------------------------
// delete devices with emty macs // delete devices with emty macs
function askDeleteDevicesWithEmptyMACs () { function askDeleteDevicesWithEmptyMACs () {
// Ask // Ask
showModalWarning('<?= lang('Maintenance_Tool_del_empty_macs_noti');?>', '<?= lang('Maintenance_Tool_del_empty_macs_noti_text');?>', showModalWarning('<?= lang('Maintenance_Tool_del_empty_macs_noti');?>', '<?= lang('Maintenance_Tool_del_empty_macs_noti_text');?>',
'Cancel', 'Delete', 'deleteDevicesWithEmptyMACs'); 'Cancel', 'Delete', 'deleteDevicesWithEmptyMACs');
} }
// -----------------------------------------------------------
function deleteDevicesWithEmptyMACs() function deleteDevicesWithEmptyMACs()
{ {
// Delete device // Delete device
@@ -580,12 +478,14 @@ function deleteDevicesWithEmptyMACs()
}); });
} }
// -----------------------------------------------------------
// delete all devices // delete all devices
function askDeleteAllDevices () { function askDeleteAllDevices () {
// Ask // Ask
showModalWarning('<?= lang('Maintenance_Tool_del_alldev_noti');?>', '<?= lang('Maintenance_Tool_del_alldev_noti_text');?>', showModalWarning('<?= lang('Maintenance_Tool_del_alldev_noti');?>', '<?= lang('Maintenance_Tool_del_alldev_noti_text');?>',
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', 'deleteAllDevices'); '<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', 'deleteAllDevices');
} }
// -----------------------------------------------------------
function deleteAllDevices() function deleteAllDevices()
{ {
// Delete device // Delete device
@@ -594,12 +494,14 @@ function deleteAllDevices()
}); });
} }
// -----------------------------------------------------------
// delete all (unknown) devices // delete all (unknown) devices
function askDeleteUnknown () { function askDeleteUnknown () {
// Ask // Ask
showModalWarning('<?= lang('Maintenance_Tool_del_unknowndev_noti');?>', '<?= lang('Maintenance_Tool_del_unknowndev_noti_text');?>', showModalWarning('<?= lang('Maintenance_Tool_del_unknowndev_noti');?>', '<?= lang('Maintenance_Tool_del_unknowndev_noti_text');?>',
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', 'deleteUnknownDevices'); '<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', 'deleteUnknownDevices');
} }
// -----------------------------------------------------------
function deleteUnknownDevices() function deleteUnknownDevices()
{ {
// Execute // Execute
@@ -608,12 +510,14 @@ function deleteUnknownDevices()
}); });
} }
// -----------------------------------------------------------
// delete all Events // delete all Events
function askDeleteEvents () { function askDeleteEvents () {
// Ask // Ask
showModalWarning('<?= lang('Maintenance_Tool_del_allevents_noti');?>', '<?= lang('Maintenance_Tool_del_allevents_noti_text');?>', showModalWarning('<?= lang('Maintenance_Tool_del_allevents_noti');?>', '<?= lang('Maintenance_Tool_del_allevents_noti_text');?>',
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', 'deleteEvents'); '<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', 'deleteEvents');
} }
// -----------------------------------------------------------
function deleteEvents() function deleteEvents()
{ {
// Execute // Execute
@@ -622,12 +526,14 @@ function deleteEvents()
}); });
} }
// -----------------------------------------------------------
// delete all Events older than 30 days // delete all Events older than 30 days
function askDeleteEvents30 () { function askDeleteEvents30 () {
// Ask // Ask
showModalWarning('<?= lang('Maintenance_Tool_del_allevents30_noti');?>', '<?= lang('Maintenance_Tool_del_allevents30_noti_text');?>', showModalWarning('<?= lang('Maintenance_Tool_del_allevents30_noti');?>', '<?= lang('Maintenance_Tool_del_allevents30_noti_text');?>',
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', 'deleteEvents30'); '<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', 'deleteEvents30');
} }
// -----------------------------------------------------------
function deleteEvents30() function deleteEvents30()
{ {
// Execute // Execute
@@ -636,6 +542,7 @@ function deleteEvents30()
}); });
} }
// -----------------------------------------------------------
// delete History // delete History
function askDeleteActHistory () { function askDeleteActHistory () {
// Ask // Ask
@@ -650,6 +557,7 @@ function deleteActHistory()
}); });
} }
// -----------------------------------------------------------
// Backup DB to Archive // Backup DB to Archive
function askPiaBackupDBtoArchive () { function askPiaBackupDBtoArchive () {
// Ask // Ask
@@ -664,6 +572,7 @@ function PiaBackupDBtoArchive()
}); });
} }
// -----------------------------------------------------------
// Restore DB from Archive // Restore DB from Archive
function askPiaRestoreDBfromArchive () { function askPiaRestoreDBfromArchive () {
// Ask // Ask
@@ -678,6 +587,7 @@ function PiaRestoreDBfromArchive()
}); });
} }
// -----------------------------------------------------------
// Purge Backups // Purge Backups
function askPiaPurgeDBBackups() { function askPiaPurgeDBBackups() {
// Ask // Ask
@@ -692,22 +602,37 @@ function PiaPurgeDBBackups()
}); });
} }
// Restart Backend // -----------------------------------------------------------
function restartBackend() { // Restart Backend Python Server
// Execute
$.ajax({
method: "POST",
url: "php/server/util.php",
data: { function: 'restartBackend' },
success: function(data, textStatus) {
showModalOk ('Result', data );
}
})
function askRestartBackend() {
// Ask
showModalWarning('<?= lang('Maint_RestartServer');?>', '<?= lang('Maint_Restart_Server_noti_text');?>',
'<?= lang('Gen_Cancel');?>', '<?= lang('Maint_RestartServer');?>', 'restartBackend');
} }
// -----------------------------------------------------------
function restartBackend() {
modalEventStatusId = 'modal-message-front-event'
// Execute
$.ajax({
method: "POST",
url: "php/server/util.php",
data: { function: "addToExecutionQueue", action: 'cron_restart_backend' },
success: function(data, textStatus) {
// showModalOk ('Result', data );
// show message
showModalOk(getString("general_event_title"), `${getString("general_event_description")} <br/> <br/> <code id='${modalEventStatusId}'></code>`);
updateModalState()
}
})
}
// -----------------------------------------------------------
// Export CSV // Export CSV
function askExportCSV() { function askExportCSV() {
// Ask // Ask
@@ -720,6 +645,7 @@ function ExportCSV()
openInNewTab("php/server/devices.php?action=ExportCSV") openInNewTab("php/server/devices.php?action=ExportCSV")
} }
// -----------------------------------------------------------
// Import CSV // Import CSV
function askImportCSV() { function askImportCSV() {
// Ask // Ask
@@ -952,13 +878,31 @@ function initializeTabs () {
} }
//------------------------------------------------------------------------------
function renderLogs(customData) {
$.ajax({
url: 'php/components/logs.php', // PHP script URL
type: 'POST', // Use POST method to send data
dataType: 'html', // Expect HTML response
// data: { items: JSON.stringify(customData) }, // Send customData as JSON
success: function(response) {
$('#logsPlc').html(response); // Replace container content with fetched HTML
},
error: function(xhr, status, error) {
console.error('Error fetching infoboxes:', error);
}
});
}
// load footer asynchronously not to block the page load/other sections
// Init
window.onload = function asyncFooter() window.onload = function asyncFooter()
{ {
initializeSelectedColumns(); initializeSelectedColumns();
scrollDown(); renderLogs();
initializeTabs(); scrollDown(); // scroll down the logs
// initializeTabs();
$("#lastCommit").append('<a href="https://github.com/jokob-sk/NetAlertX/commits" target="_blank"><img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/jokob-sk/netalertx/main?logo=github"></a>'); $("#lastCommit").append('<a href="https://github.com/jokob-sk/NetAlertX/commits" target="_blank"><img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/jokob-sk/netalertx/main?logo=github"></a>');
@@ -967,10 +911,6 @@ window.onload = function asyncFooter()
} }
// scroll to the latest log entrie sat teh bottom of the file
</script> </script>

76
front/php/components/logs.php Executable file
View File

@@ -0,0 +1,76 @@
<?php
require '../server/init.php';
// Function to render the log area component
function renderLogArea($params) {
$fileName = isset($params['fileName']) ? $params['fileName'] : '';
$filePath = isset($params['filePath']) ? $params['filePath'] : '';
$textAreaCssClass = isset($params['textAreaCssClass']) ? $params['textAreaCssClass'] : '';
$buttons = isset($params['buttons']) ? $params['buttons'] : [];
$content = "";
if(filesize($filePath) > 2000000) {
$content = file_get_contents($filePath, false, null, -2000000);
} else {
$content = file_get_contents($filePath);
}
// Render the log area HTML
$html = '
<div class="log-area box box-solid box-primary">
<div class="row logs-row col-sm-12 col-xs-12">
<textarea id="app_log" class="' . $textAreaCssClass . '" cols="70" rows="10" wrap="off" readonly>'
.$content.
'</textarea>
</div>
<div class="row logs-row">
<div class="log-file col-sm-8 col-xs-12">' . $fileName . '
<div class="logs-size">' . number_format((filesize($filePath) / 1000000), 2, ",", ".") . ' MB
<span class="span-padding"><a href="' . $filePath . '" target="_blank"><i class="fa fa-download"></i></a></span>
</div>
</div>
<div class="col-sm-4 col-xs-12">
';
// Render each button
foreach ($buttons as $button) {
$labelStringCode = isset($button['labelStringCode']) ? $button['labelStringCode'] : '';
$event = isset($button['event']) ? $button['event'] : '';
$html .= '
<div class="col-sm-6 col-xs-6">
<button class="btn btn-primary" onclick="' . $event . '">' . lang($labelStringCode) . '</button>
</div>
';
}
$html .= '
</div>
</div>
</div>
';
return $html;
}
// Load default data from JSON file
$defaultDataFile = 'logs_defaults.json';
$defaultData = file_exists($defaultDataFile) ? json_decode(file_get_contents($defaultDataFile), true) : [];
// Check if JSON data is submitted via POST
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['items'])) {
$items = json_decode($_POST['items'], true);
} else {
$items = $defaultData;
}
// Render the log areas with the retrieved or default data
$html = '';
foreach ($items as $item) {
$html .= renderLogArea($item);
}
echo $html;
exit();
?>

View File

@@ -0,0 +1,80 @@
[
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('app.log', 'cleanLog')"
},
{
"labelStringCode": "Maint_RestartServer",
"event": "askRestartBackend()"
}
],
"fileName": "app.log",
"filePath": "/app/front/log/app.log",
"textAreaCssClass": "logs"
},
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('app_front.log', 'cleanLog')"
}
],
"fileName": "app_front.log",
"filePath": "/app/front/log/app_front.log",
"textAreaCssClass": "logs logs-small"
},
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('app.php_errors.log', 'cleanLog')"
}
],
"fileName": "app.php_errors.log",
"filePath": "/app/front/log/app.php_errors.log",
"textAreaCssClass": "logs logs-small"
},
{
"buttons": [
],
"fileName": "nginx/error.log",
"filePath": "/var/log/nginx/error.log",
"textAreaCssClass": "logs logs-small"
},
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('app_front.log', 'cleanLog')"
}
],
"fileName": "app_front.log",
"filePath": "/app/front/log/app_front.log",
"textAreaCssClass": "logs logs-small"
},
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('stdout.log', 'cleanLog')"
}
],
"fileName": "stdout.log",
"filePath": "/app/front/log/stdout.log",
"textAreaCssClass": "logs logs-small"
},
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('stderr.log', 'cleanLog')"
}
],
"fileName": "stderr.log",
"filePath": "/app/front/log/stderr.log",
"textAreaCssClass": "logs logs-small"
}
]

View File

@@ -28,10 +28,7 @@ if(array_key_exists('settings', $_REQUEST) != FALSE)
// call functions based on requested params // call functions based on requested params
switch ($FUNCTION) { switch ($FUNCTION) {
case 'restartBackend':
restartBackend();
break;
case 'savesettings': case 'savesettings':
saveSettings(); saveSettings();
@@ -228,6 +225,7 @@ function displayMessage($message, $logAlert = FALSE, $logConsole = TRUE, $logFil
} }
// ----------------------------------------------------------------------------------------
// Adds an action to perform into the execution_queue.log file // Adds an action to perform into the execution_queue.log file
function addToExecutionQueue($action) function addToExecutionQueue($action)
{ {
@@ -247,27 +245,6 @@ function addToExecutionQueue($action)
} }
// ----------------------------------------------------------------------------------------
function restartBackend()
{
$command = 'pkill -f "python /app/server" && (python /app/server > /dev/null 2>&1 &) && echo "done" 2>&1';
// Execute the command
$output = [];
$output_str = "";
$return_var = 0;
exec($command, $output, $return_var);
// Format the output
foreach ($output as $line) {
$output_str .= $line . "\n";
}
echo "Command result: $return_var, $output_str";
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
function cleanLog($logFile) function cleanLog($logFile)

View File

@@ -384,6 +384,9 @@
"MQTT_USER_name": "MQTT user", "MQTT_USER_name": "MQTT user",
"MQTT_display_name": "MQTT", "MQTT_display_name": "MQTT",
"MQTT_icon": "<i class=\"fa fa-square-rss\"></i>", "MQTT_icon": "<i class=\"fa fa-square-rss\"></i>",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "Installierte Version", "Maintenance_Running_Version": "Installierte Version",
"Maintenance_Status": "Status", "Maintenance_Status": "Status",
"Maintenance_Title": "Wartungswerkzeuge", "Maintenance_Title": "Wartungswerkzeuge",

View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "Password Alert!", "Login_Toggle_Alert_headline": "Password Alert!",
"Login_Toggle_Info": "Password Information", "Login_Toggle_Info": "Password Information",
"Login_Toggle_Info_headline": "Password Information", "Login_Toggle_Info_headline": "Password Information",
"Maint_PurgeLog": "Purge log",
"Maint_RestartServer": "Restart server",
"Maint_Restart_Server_noti_text": "Are you sure you want to restart the backend server? This may casue app inconsistency. Backup your setup first. <br/> <br/> Note: This may take a few minutes.",
"Maintenance_Running_Version": "Installed version", "Maintenance_Running_Version": "Installed version",
"Maintenance_Status": "Status", "Maintenance_Status": "Status",
"Maintenance_Title": "Maintenance tools", "Maintenance_Title": "Maintenance tools",

View File

@@ -382,6 +382,9 @@
"MQTT_USER_name": "Usuario de MQTT", "MQTT_USER_name": "Usuario de MQTT",
"MQTT_display_name": "MQTT", "MQTT_display_name": "MQTT",
"MQTT_icon": "<i class=\"fa fa-square-rss\"></i>", "MQTT_icon": "<i class=\"fa fa-square-rss\"></i>",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "Versión instalada", "Maintenance_Running_Version": "Versión instalada",
"Maintenance_Status": "Situación", "Maintenance_Status": "Situación",
"Maintenance_Title": "Herramientas de mantenimiento", "Maintenance_Title": "Herramientas de mantenimiento",

View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "", "Login_Toggle_Alert_headline": "",
"Login_Toggle_Info": "", "Login_Toggle_Info": "",
"Login_Toggle_Info_headline": "", "Login_Toggle_Info_headline": "",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "Version installée", "Maintenance_Running_Version": "Version installée",
"Maintenance_Status": "État", "Maintenance_Status": "État",
"Maintenance_Title": "Outils d'entretien", "Maintenance_Title": "Outils d'entretien",

View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "Avviso password!", "Login_Toggle_Alert_headline": "Avviso password!",
"Login_Toggle_Info": "Informazioni password", "Login_Toggle_Info": "Informazioni password",
"Login_Toggle_Info_headline": "Informazioni password", "Login_Toggle_Info_headline": "Informazioni password",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "Versione installata", "Maintenance_Running_Version": "Versione installata",
"Maintenance_Status": "Stato", "Maintenance_Status": "Stato",
"Maintenance_Title": "Strumenti di manutenzione", "Maintenance_Title": "Strumenti di manutenzione",

View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "Passord Varsling!", "Login_Toggle_Alert_headline": "Passord Varsling!",
"Login_Toggle_Info": "Passordinformasjon", "Login_Toggle_Info": "Passordinformasjon",
"Login_Toggle_Info_headline": "Passordinformasjon", "Login_Toggle_Info_headline": "Passordinformasjon",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "Installert versjon", "Maintenance_Running_Version": "Installert versjon",
"Maintenance_Status": "Status", "Maintenance_Status": "Status",
"Maintenance_Title": "Vedlikeholdsverktøy", "Maintenance_Title": "Vedlikeholdsverktøy",

View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "Alert Hasła!", "Login_Toggle_Alert_headline": "Alert Hasła!",
"Login_Toggle_Info": "Informacje o haśle", "Login_Toggle_Info": "Informacje o haśle",
"Login_Toggle_Info_headline": "Informacje o haśle", "Login_Toggle_Info_headline": "Informacje o haśle",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "Zainstalowana wersja", "Maintenance_Running_Version": "Zainstalowana wersja",
"Maintenance_Status": "Status", "Maintenance_Status": "Status",
"Maintenance_Title": "Narzędzia konserwacyjne", "Maintenance_Title": "Narzędzia konserwacyjne",

View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "", "Login_Toggle_Alert_headline": "",
"Login_Toggle_Info": "", "Login_Toggle_Info": "",
"Login_Toggle_Info_headline": "", "Login_Toggle_Info_headline": "",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "", "Maintenance_Running_Version": "",
"Maintenance_Status": "", "Maintenance_Status": "",
"Maintenance_Title": "", "Maintenance_Title": "",

3
front/php/templates/language/ru_ru.json Normal file → Executable file
View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "Предупреждение о пароле!", "Login_Toggle_Alert_headline": "Предупреждение о пароле!",
"Login_Toggle_Info": "Информация о пароле", "Login_Toggle_Info": "Информация о пароле",
"Login_Toggle_Info_headline": "Информация о пароле", "Login_Toggle_Info_headline": "Информация о пароле",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "Установленная версия", "Maintenance_Running_Version": "Установленная версия",
"Maintenance_Status": "Статус", "Maintenance_Status": "Статус",
"Maintenance_Title": "Инструменты обслуживания", "Maintenance_Title": "Инструменты обслуживания",

View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "", "Login_Toggle_Alert_headline": "",
"Login_Toggle_Info": "", "Login_Toggle_Info": "",
"Login_Toggle_Info_headline": "", "Login_Toggle_Info_headline": "",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "", "Maintenance_Running_Version": "",
"Maintenance_Status": "", "Maintenance_Status": "",
"Maintenance_Title": "", "Maintenance_Title": "",

View File

@@ -358,6 +358,9 @@
"Login_Toggle_Alert_headline": "", "Login_Toggle_Alert_headline": "",
"Login_Toggle_Info": "", "Login_Toggle_Info": "",
"Login_Toggle_Info_headline": "", "Login_Toggle_Info_headline": "",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_Running_Version": "", "Maintenance_Running_Version": "",
"Maintenance_Status": "", "Maintenance_Status": "",
"Maintenance_Title": "", "Maintenance_Title": "",

5
install/crontab Executable file
View File

@@ -0,0 +1,5 @@
# Schedule cron jobs
* * * * * /app/back/cron_script.sh
* * * * * echo "$(date +'%Y-%m-%d %H:%M:%S') - Cron job ran" >> /app/front/log/cron_timestamp.log

View File

@@ -752,8 +752,9 @@ def check_and_run_user_event(db, all_plugins, pluginsState):
# Check if the log file exists # Check if the log file exists
logFile = os.path.join(logPath, "execution_queue.log") logFile = os.path.join(logPath, "execution_queue.log")
# track if not an API event # Track if not an API event and list of executed events
show_events_completed = False show_events_completed = False
executed_events = []
if not os.path.exists(logFile): if not os.path.exists(logFile):
return pluginsState return pluginsState
@@ -761,11 +762,14 @@ def check_and_run_user_event(db, all_plugins, pluginsState):
with open(logFile, "r") as file: with open(logFile, "r") as file:
lines = file.readlines() lines = file.readlines()
remaining_lines = []
for line in lines: for line in lines:
# Split the line by '|', and take the third and fourth columns (indices 2 and 3) # Split the line by '|', and take the third and fourth columns (indices 2 and 3)
columns = line.strip().split('|')[2:4] columns = line.strip().split('|')[2:4]
if len(columns) != 2: if len(columns) != 2:
remaining_lines.append(line)
continue continue
event, param = columns event, param = columns
@@ -773,19 +777,26 @@ def check_and_run_user_event(db, all_plugins, pluginsState):
if event == 'test': if event == 'test':
show_events_completed = True show_events_completed = True
pluginsState = handle_test(param, db, all_plugins, pluginsState) pluginsState = handle_test(param, db, all_plugins, pluginsState)
if event == 'run': executed_events.append(f"test with param {param}")
elif event == 'run':
show_events_completed = True show_events_completed = True
pluginsState = handle_run(param, db, all_plugins, pluginsState) pluginsState = handle_run(param, db, all_plugins, pluginsState)
if event == 'update_api': executed_events.append(f"run with param {param}")
# update API endpoints elif event == 'update_api':
# Update API endpoints
update_api(db, all_plugins, False, param.split(',')) update_api(db, all_plugins, False, param.split(','))
executed_events.append(f"update_api with param {param}")
else:
remaining_lines.append(line)
# Clear the log file # Rewrite the log file with remaining lines
open(logFile, "w").close() with open(logFile, "w") as file:
file.writelines(remaining_lines)
# only show pop up if not an API event # Only show pop-up if not an API event
if show_events_completed: if show_events_completed:
write_notification('[Ad-hoc events] All Events executed', 'interrupt', timeNowTZ()) executed_events_message = ', '.join(executed_events)
write_notification(f'[Ad-hoc events] Events executed: {executed_events_message}', 'interrupt', timeNowTZ())
return pluginsState return pluginsState