mirror of
https://github.com/nextcloud/nextcloudpi.git
synced 2026-01-10 15:12:01 -03:30
ncp-web: use SSE to display process output in real time. Exit status green/red
This commit is contained in:
parent
edccf4a7e1
commit
f044c6d6b2
34
ncp-web/green-circle.svg
Normal file
34
ncp-web/green-circle.svg
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="11.457627"
|
||||
width="11.288136"
|
||||
viewbox="0 0 599 599"
|
||||
id="Green circle"
|
||||
version="1.1">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<ellipse
|
||||
ry="5.7288136"
|
||||
rx="5.6440678"
|
||||
cy="5.7288136"
|
||||
cx="5.6440678"
|
||||
style="fill:#339933;stroke-width:1.42157066"
|
||||
id="green_circle" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 890 B |
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
NextcloudPi Web Panel javascript library
|
||||
NextcloudPi Web Panel frontend
|
||||
|
||||
Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
|
||||
GPL licensed (see end of file) * Use at your own risk!
|
||||
@ -20,7 +20,7 @@
|
||||
session_start();
|
||||
|
||||
// security headers
|
||||
header("Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';");
|
||||
header("Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; object-src 'self';");
|
||||
header("X-XSS-Protection: 1; mode=block");
|
||||
header("X-Content-Type-Options: nosniff");
|
||||
header("X-Robots-Tag: none");
|
||||
@ -117,6 +117,7 @@
|
||||
<div id="config-button-wrapper">
|
||||
<button id="config-button">Run</button>
|
||||
<img id="loading-gif" src="loading-small.gif">
|
||||
<div id="circle-retstatus" class="icon-red-circle"></div>
|
||||
</div>
|
||||
</form>
|
||||
<textarea readonly id="details-box" rows="25" cols="60"></textarea>
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
include ('csrf.php');
|
||||
|
||||
session_start();
|
||||
ignore_user_abort( true );
|
||||
|
||||
if ( $_POST['action'] == "cfgreq" )
|
||||
{
|
||||
@ -97,9 +98,11 @@ else if ( $_POST['action'] == "launch" && $_POST['config'] )
|
||||
|
||||
// Get new token
|
||||
echo '{ "token": "' . getCSRFToken() . '",';
|
||||
echo ' "output": ';
|
||||
echo ' "output": "" , ';
|
||||
echo ' "ret": ';
|
||||
|
||||
echo json_encode( shell_exec( 'bash -c "sudo /home/www/ncp-launcher.sh ' . $file . '"' ) ) . ' }';
|
||||
exec( 'bash -c "sudo /home/www/ncp-launcher.sh ' . $file . '"' , $output , $ret );
|
||||
echo '"' . $ret . '" }';
|
||||
}
|
||||
|
||||
else if ( $_POST['action'] == "poweroff" )
|
||||
|
||||
93
ncp-web/ncp-output.php
Normal file
93
ncp-web/ncp-output.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
///
|
||||
// Dispatcher of SSE events with the contents of the NCP log
|
||||
//
|
||||
// Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
|
||||
// GPL licensed (see end of file) * Use at your own risk!
|
||||
//
|
||||
// More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/
|
||||
///
|
||||
|
||||
header('Content-Type: text/event-stream; charset=utf-8');
|
||||
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the SSE data format and flushes that data to the client.
|
||||
* ( from html5rocks.com )
|
||||
*
|
||||
* @param string $id Timestamp/id of this connection.
|
||||
* @param string $msg Line of text that should be transmitted.
|
||||
*/
|
||||
function sendMsg($id, $msg)
|
||||
{
|
||||
echo "id: $id" . PHP_EOL;
|
||||
echo "data: $msg" . PHP_EOL;
|
||||
echo PHP_EOL;
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pings the client-browser to force detection of closed socket
|
||||
*/
|
||||
function pingClient()
|
||||
{
|
||||
echo ' ';
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Imitates 'tail --follow' functionality, and sends lines as SSE events
|
||||
* , while pinging browser to detect closed tab.
|
||||
* ( based on stack overflow )
|
||||
*/
|
||||
function follow($file)
|
||||
{
|
||||
$size = 0;
|
||||
while (true)
|
||||
{
|
||||
clearstatcache();
|
||||
$currentSize = filesize($file);
|
||||
if ($size == $currentSize)
|
||||
{
|
||||
usleep(200000); // 0.2s
|
||||
// if the user refreshes the tab >5 times, it won't load because it doesn't detect closed socket
|
||||
// , and all workers are in use
|
||||
pingClient();
|
||||
continue;
|
||||
}
|
||||
|
||||
$fh = fopen($file, "r");
|
||||
fseek($fh, $size);
|
||||
|
||||
while ($line = fgets($fh))
|
||||
sendMsg( 'output' , $line );
|
||||
|
||||
fclose($fh);
|
||||
$size = $currentSize;
|
||||
}
|
||||
}
|
||||
|
||||
session_write_close();
|
||||
echo str_pad('',1024*1024*4); // make sure the browser buffer becomes full
|
||||
follow( '/run/ncp.log' );
|
||||
|
||||
// License
|
||||
//
|
||||
// This script is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This script is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this script; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
// Boston, MA 02111-1307 USA
|
||||
?>
|
||||
@ -1113,6 +1113,18 @@ select {
|
||||
background-image: url('poweroff.svg');
|
||||
}
|
||||
|
||||
.icon-red-circle {
|
||||
background-image: url('red-circle.svg');
|
||||
padding: 8px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.icon-green-circle {
|
||||
background-image: url('green-circle.svg');
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
|
||||
#expand #expandDisplayName {
|
||||
padding: 8px;
|
||||
opacity: 0.6;
|
||||
|
||||
@ -19,6 +19,25 @@ function errorMsg()
|
||||
|
||||
$(function()
|
||||
{
|
||||
// Event source to receive process output in real time
|
||||
if (!!window.EventSource)
|
||||
var source = new EventSource('ncp-output.php');
|
||||
else
|
||||
$('#config-box-title').fill( "Browser not supported" );
|
||||
|
||||
source.addEventListener('message', function(e)
|
||||
{
|
||||
if ( e.origin != 'https://' + window.location.hostname + ':4443')
|
||||
{
|
||||
$('#details-box').fill( "Invalid origin" );
|
||||
return;
|
||||
}
|
||||
|
||||
var textarea = $('#details-box');
|
||||
textarea.fill( textarea.text() + e.data + '\n' );
|
||||
textarea[0].scrollTop = textarea[0].scrollHeight;
|
||||
}, false);
|
||||
|
||||
// Show selected option configuration box
|
||||
$( 'li' , '#app-navigation' ).on('click', function(e)
|
||||
{
|
||||
@ -38,6 +57,7 @@ $(function()
|
||||
var ret = $.parseJSON( result );
|
||||
if ( ret.token )
|
||||
$('#csrf-token').set( { value: ret.token } );
|
||||
$('#circle-retstatus').hide();
|
||||
$('#config-box').ht( ret.output );
|
||||
$('#config-box-title').fill( $( 'input' , '#' + selectedID ).get( '.value' ) );
|
||||
$('#config-box-wrapper').show();
|
||||
@ -64,6 +84,11 @@ $(function()
|
||||
cfg[item.name] = item.value;
|
||||
} );
|
||||
|
||||
// reset box
|
||||
$('#details-box').fill();
|
||||
$('#details-box').show();
|
||||
$('#circle-retstatus').hide();
|
||||
|
||||
// request
|
||||
$.request('post', 'ncp-launcher.php', { action:'launch',
|
||||
ref:selectedID ,
|
||||
@ -74,8 +99,14 @@ $(function()
|
||||
var ret = $.parseJSON( result );
|
||||
if ( ret.token )
|
||||
$('#csrf-token').set( { value: ret.token } );
|
||||
$('#details-box').fill(ret.output);
|
||||
$('#details-box').show();
|
||||
if ( ret.ret ) // means that the process was launched
|
||||
{
|
||||
if ( ret.ret == '0' ) $('#circle-retstatus').set( '+icon-green-circle' );
|
||||
else $('#circle-retstatus').set( '-icon-green-circle' );
|
||||
$('#circle-retstatus').show();
|
||||
}
|
||||
else // print error from server instead
|
||||
$('#details-box').fill(ret.output);
|
||||
$('#config-button').set('@disabled',null);
|
||||
$('#loading-gif').hide();
|
||||
confLock = false;
|
||||
|
||||
33
ncp-web/red-circle.svg
Normal file
33
ncp-web/red-circle.svg
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="11.118644"
|
||||
width="11.118644"
|
||||
viewbox="0 0 0 0"
|
||||
id="Red circle"
|
||||
version="1.1">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<circle
|
||||
r="5.5593219"
|
||||
cy="5.5593219"
|
||||
cx="5.5593219"
|
||||
style="fill:#ff0000;stroke-width:1.38983047"
|
||||
id="red_circle" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 860 B |
@ -60,7 +60,10 @@ DIR=/usr/local/etc/nextcloudpi-config.d
|
||||
test -f $DIR/$1 || { echo "File not found"; exit 1; }
|
||||
source /usr/local/etc/library.sh
|
||||
cd $DIR
|
||||
launch_script $1
|
||||
touch /run/ncp.log
|
||||
chmod 640 /run/ncp.log
|
||||
chown root:www-data /run/ncp.log
|
||||
launch_script $1 &> /run/ncp.log
|
||||
EOF
|
||||
chmod 700 /home/www/ncp-launcher.sh
|
||||
echo "www-data ALL = NOPASSWD: /home/www/ncp-launcher.sh , /sbin/halt" >> /etc/sudoers
|
||||
|
||||
14
update.sh
14
update.sh
@ -119,6 +119,20 @@ sed -i 's|www-data.*|www-data ALL = NOPASSWD: /home/www/ncp-launcher.sh , /sbin/
|
||||
# fix fail2ban misconfig in stretch
|
||||
rm -f /etc/fail2ban/jail.d/defaults-debian.conf
|
||||
|
||||
# update ncp-launcher to support realtime updates with SSE
|
||||
cat > /home/www/ncp-launcher.sh <<'EOF'
|
||||
#!/bin/bash
|
||||
DIR=/usr/local/etc/nextcloudpi-config.d
|
||||
test -f $DIR/$1 || { echo "File not found"; exit 1; }
|
||||
source /usr/local/etc/library.sh
|
||||
cd $DIR
|
||||
touch /run/ncp.log
|
||||
chmod 640 /run/ncp.log
|
||||
chown root:www-data /run/ncp.log
|
||||
launch_script $1 &> /run/ncp.log
|
||||
EOF
|
||||
chmod 700 /home/www/ncp-launcher.sh
|
||||
|
||||
# License
|
||||
#
|
||||
# This script is free software; you can redistribute it and/or modify it
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user