Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Optionally) run ncp apps in tmux #796

Open
wants to merge 22 commits into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c9768d2
library: Optionally execute ncp-app in tmux if set in app cfg
Feb 8, 2019
0dbc586
library: Fix return value not being retrieved from tmux'ed script
Feb 8, 2019
d91a5f5
update/install: Install tmux and dependencies on installation/update
Feb 8, 2019
a3c2edf
library: Fix formatting
Feb 8, 2019
88ed633
library: Fix valid return values from tmux not being accepted
Feb 8, 2019
33f44f8
Separate function for attaching to running ncp app's tmux session.
Feb 10, 2019
d707807
ncp-launcher.sh: Add parameter to check if an ncp-app is running
Feb 16, 2019
8bf2d85
ncp-web: Implement foundation for different server push message types
Feb 16, 2019
8d62991
library.sh: Fix tmux logs not being appended to ncp.log
Feb 17, 2019
5664109
Move ncp-web refactoring to separate branch
Feb 17, 2019
4fd441d
ncp-web: Check if any app is running and attach if that is the case
Feb 17, 2019
bff0bc1
Remove vscode config from .gitignore
theCalcaholic Feb 19, 2019
2a4ee28
library.sh: Remove commented code
theCalcaholic Feb 19, 2019
cd8451d
ncp-web: Remove debug output and unnecessary variable declarations
theCalcaholic Feb 19, 2019
6c8e95c
library.sh: A number of fixes suggested in Github review
theCalcaholic Feb 19, 2019
467dc01
Move lock file to /run/ncp.lock
theCalcaholic Feb 19, 2019
59fe7ce
library.sh: Fix erroneously unescaped quotes
theCalcaholic Feb 19, 2019
a357f2c
update.sh: Create log dir and updated ncp-launcher.sh
theCalcaholic Feb 19, 2019
a0b9b28
library.sh: Restructure run_app_unsafe()
theCalcaholic Feb 19, 2019
aaa4202
ncp-launcher.sh: Remove unused aguments
theCalcaholic Feb 22, 2019
e2edadf
ncp.sh,update.sh: Improve installation of tmux, locale and new log di…
theCalcaholic Feb 22, 2019
5da8938
library.sh: Give more relevant messages depending on whether an app i…
theCalcaholic Feb 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ raspbian_boot
ncp-web/wizard.cfg
ncp-web/ncp-web.cfg
docker-armhf/qemu-arm-static
.vagrant/
.vagrant/
6 changes: 3 additions & 3 deletions bin/ncp/CONFIG/nc-autoupdate-nc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ configure()
cat > /etc/cron.daily/ncp-autoupdate-nc <<EOF
#!/bin/bash

echo -e "[ncp-update-nc]" >> /var/log/ncp.log
/usr/local/bin/ncp-update-nc "$VERSION" 2>&1 | tee -a /var/log/ncp.log
echo -e "[ncp-update-nc]" >> /var/log/ncp/ncp.log
/usr/local/bin/ncp-update-nc "$VERSION" 2>&1 | tee -a /var/log/ncp/ncp.log

if [[ \${PIPESTATUS[0]} -eq 0 ]]; then

Expand All @@ -33,7 +33,7 @@ if [[ \${PIPESTATUS[0]} -eq 0 ]]; then
sudo -u www-data php /var/www/nextcloud/occ notification:generate \
"$NOTIFYUSER" "NextCloudPi" -l "Nextcloud was updated to \$VER"
fi
echo "" >> /var/log/ncp.log
echo "" >> /var/log/ncp/ncp.log
EOF
chmod 755 /etc/cron.daily/ncp-autoupdate-nc
echo "automatic Nextcloud updates enabled"
Expand Down
6 changes: 3 additions & 3 deletions bin/ncp/CONFIG/nc-update-nc-apps-auto.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ configure()

cat > "$cronfile" <<'EOF'
#!/bin/bash
echo "[ nc-update-nc-apps-auto ]" >> /var/log/ncp.log
echo "checking for updates..." >> /var/log/ncp.log
ncc app:update --all -n >> /var/log/ncp.log
echo "[ nc-update-nc-apps-auto ]" >> /var/log/ncp/ncp.log
echo "checking for updates..." >> /var/log/ncp/ncp.log
ncc app:update --all -n >> /var/log/ncp/ncp.log
EOF
chmod 755 "$cronfile"
echo "automatic app updates enabled"
Expand Down
196 changes: 159 additions & 37 deletions etc/library.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

CFGDIR=/usr/local/etc/ncp-config.d
BINDIR=/usr/local/bin/ncp
LOCK_FILE=/run/ncp.lock
LOG=/var/log/ncp/ncp.log

function configure_app()
{
Expand All @@ -22,14 +24,16 @@ function configure_app()
type dialog &>/dev/null || { echo "please, install dialog for interactive configuration"; return 1; }
[[ -f "$cfg_file" ]] || return 0;

local cfg="$( cat "$cfg_file" )"
local len="$(jq '.params | length' <<<"$cfg")"
local cfg len
cfg="$( cat "$cfg_file" )"
len="$(jq '.params | length' <<<"$cfg")"
[[ $len -eq 0 ]] && return

# read cfg parameters
for (( i = 0 ; i < len ; i++ )); do
local var="$(jq -r ".params[$i].id" <<<"$cfg")"
local val="$(jq -r ".params[$i].value" <<<"$cfg")"
local var val
var="$(jq -r ".params[$i].id" <<<"$cfg")"
val="$(jq -r ".params[$i].value" <<<"$cfg")"
local vars+=("$var")
local vals+=("$val")
local idx=$((i+1))
Expand Down Expand Up @@ -91,8 +95,9 @@ function configure_app()

function run_app()
{
local ncp_app=$1
local script="$(find "$BINDIR" -name $ncp_app.sh)"
local script ncp_app
ncp_app=$1
script="$(find "$BINDIR" -name "$ncp_app.sh")"

[[ -f "$script" ]] || { echo "file $script not found"; return 1; }

Expand All @@ -102,42 +107,153 @@ function run_app()
# receives a script file, no security checks
function run_app_unsafe()
{
local script=$1
local ncp_app="$(basename "$script" .sh)"
local script ncp_app
script=$1
ncp_app="$(basename "$script" .sh)"
local cfg_file="$CFGDIR/$ncp_app.cfg"
local log=/var/log/ncp.log

[[ -f "$script" ]] || { echo "file $script not found"; return 1; }

touch $log
chmod 640 $log
chown root:www-data $log
touch "$LOG"
chmod 640 "$LOG"
chown root:www-data "$LOG"

echo "Running $ncp_app"
echo "[ $ncp_app ]" >> $log

# read script
attach_and_exit_if_running

unset configure
source "$script"
(
# read cfg parameters
[[ -f "$cfg_file" ]] && {
local len cfg
cfg="$( cat "$cfg_file" )"
jq -e '.tmux' <<<"$cfg" &>/dev/null
local use_tmux="$?"
len="$(jq '.params | length' <<<"$cfg")"
for (( i = 0 ; i < len ; i++ )); do
local var val
var="$(jq -r ".params[$i].id" <<<"$cfg")"
val="$(jq -r ".params[$i].value" <<<"$cfg")"
eval "export $var=$val"
done
}

echo "$ncp_app" > "$LOCK_FILE"
if which tmux > /dev/null && [[ $use_tmux == 0 ]]
then
run_app_in_tmux "$ncp_app" "$script"
else
# shellcheck disable=SC2064
trap "rm '$LOCK_FILE'" EXIT SIGHUP SIGINT SIGQUIT SIGILL SIGABRT SIGSEV SIGTERM SIGIO
echo "[ $ncp_app ]" | tee -a "$LOG"
echo "Closing the browser/terminal session will interrupt $ncp_app!" | tee -a "$LOG"
# read script
# shellcheck source=/dev/null
source "$script"
# run
configure 2>&1 | tee -a "$LOG"
local ret="${PIPESTATUS[0]}"
exit "$ret"
fi
)
ret="$?"
echo "" >> "$LOG"

# read cfg parameters
[[ -f "$cfg_file" ]] && {
local cfg="$( cat "$cfg_file" )"
local len="$(jq '.params | length' <<<"$cfg")"
for (( i = 0 ; i < len ; i++ )); do
local var="$(jq -r ".params[$i].id" <<<"$cfg")"
local val="$(jq -r ".params[$i].value" <<<"$cfg")"
eval "$var=$val"
done
return "$ret"
}

function run_app_in_tmux()
{
local ncp_app="$1"
local script="$2"

echo "You can safely exit. $ncp_app will keep running until it's done." | tee -a "$LOG"
echo "Reattach at any time by running the app again." | tee -a "$LOG"
# Run app in tmux
local tmux_log_file tmux_status_file LIBPATH
tmux_log_file="/var/log/ncp/tmux.${ncp_app}.log"
tmux_status_file="/var/log/ncp/tmux.${ncp_app}.status"
LIBPATH="$(dirname "$CFGDIR")/library.sh"

# Reset tmux output
echo "[ $ncp_app ]" >> "$LOG"
echo "[ $ncp_app ]" > "$tmux_log_file"
echo "" > "$tmux_status_file"
chmod 640 "$tmux_log_file" "$tmux_status_file"
chown root:www-data "$tmux_log_file" "$tmux_status_file"

tmux new-session -d -s "$ncp_app" "bash -c '(
trap \"echo \\\$? > $tmux_status_file && rm $LOCK_FILE\" 1 2 3 4 6 9 11 15 19 29
source \"$LIBPATH\"
source \"$script\"
configure 2>&1 | tee -a \"$LOG\"
echo \"\${PIPESTATUS[0]}\" > $tmux_status_file
rm $LOCK_FILE
)' 2>&1 | tee -a $tmux_log_file"

attach_to_app "$ncp_app"
return $?
}

function attach_and_exit_if_running()
{
# Check if app is already running in tmux
local running_app
running_app=$( [[ -f "$LOCK_FILE" ]] && cat "$LOCK_FILE" || echo "" )
[[ ! -z $running_app ]] && which tmux >/dev/null && tmux has-session -t="$running_app" &>/dev/null && {

local choice question
[[ $ATTACH_TO_RUNNING == "1" ]] && choice="y"
[[ $ATTACH_TO_RUNNING == "0" ]] && choice="n"
question="An app ($running_app) is already running. Do you want to attach to it's output? <y/n> "
if [[ $choice == "y" ]] || [[ $choice == "n" ]]
then
echo "$question"
echo "Choice: <$choice>"
else
read -rp "$question" choice
while [[ "$choice" != "y" ]] && [[ "$choice" != "n" ]]
do
echo "choice was '$choice'"
read -rp "Invalid choice. y or n expected." choice
done
fi

if [[ "$choice" == "y" ]]
then
attach_to_app "$running_app"
fi
exit $?
}
return 0
}

# run
configure 2>&1 | tee -a $log
local ret="${PIPESTATUS[0]}"
function attach_to_app()
{
local tmux_log_file tmux_status_file
tmux_log_file="/var/log/ncp/tmux.${ncp_app}.log"
tmux_status_file="/var/log/ncp/tmux.${ncp_app}.status"

if [[ "$ATTACH_NO_FOLLOW" == "1" ]]
then
cat "$tmux_log_file"
return 0
else
(while tmux has-session -t="$ncp_app" > /dev/null 2>&1
do
sleep 1
done) &

echo "" >> $log
# Follow log file until tmux session has terminated
tail --lines=+0 -f "$tmux_log_file" --pid="$!"
fi

return "$ret"
# Read return value from tmux log file
ret="$(tail -n 1 "$tmux_status_file")"

[[ $ret =~ ^[0-9]+$ ]] && return $ret
return 1
}

function is_active_app()
Expand All @@ -147,18 +263,20 @@ function is_active_app()
local script="$bin_dir/$ncp_app.sh"
local cfg_file="$CFGDIR/$ncp_app.cfg"

[[ -f "$script" ]] || local script="$(find "$BINDIR" -name $ncp_app.sh)"
[[ -f "$script" ]] || script="$(find "$BINDIR" -name $ncp_app.sh)"
[[ -f "$script" ]] || { echo "file $script not found"; return 1; }

# function
unset is_active
# shellcheck source=/dev/null
nachoparker marked this conversation as resolved.
Show resolved Hide resolved
source "$script"
[[ $( type -t is_active ) == function ]] && { is_active; return $?; }

# config
[[ -f "$cfg_file" ]] || return 1

local cfg="$( cat "$cfg_file" )"
local cfg
cfg="$( cat "$cfg_file" )"
[[ "$(jq -r ".params[0].id" <<<"$cfg")" == "ACTIVE" ]] && \
[[ "$(jq -r ".params[0].value" <<<"$cfg")" == "yes" ]] && \
return 0
Expand All @@ -170,9 +288,10 @@ function info_app()
local ncp_app=$1
local cfg_file="$CFGDIR/$ncp_app.cfg"

local cfg="$( cat "$cfg_file" 2>/dev/null )"
local info=$( jq -r .info <<<"$cfg" )
local infotitle=$( jq -r .infotitle <<<"$cfg" )
local cfg info infotitle
cfg="$( cat "$cfg_file" 2>/dev/null )"
info=$( jq -r .info <<<"$cfg" )
infotitle=$( jq -r .infotitle <<<"$cfg" )

[[ "$info" == "" ]] || [[ "$info" == "null" ]] && return 0
[[ "$infotitle" == "" ]] || [[ "$infotitle" == "null" ]] && infotitle="Info"
Expand All @@ -187,18 +306,20 @@ function info_app()

function install_app()
{
local script
local ncp_app=$1

# $1 can be either an installed app name or an app script
if [[ -f "$ncp_app" ]]; then
local script="$ncp_app"
local ncp_app="$(basename "$script" .sh)"
script="$ncp_app"
ncp_app="$(basename "$script" .sh)"
else
local script="$(find "$BINDIR" -name $ncp_app.sh)"
script="$(find "$BINDIR" -name $ncp_app.sh)"
fi

# do it
unset install
# shellcheck source=/dev/null
source "$script"
echo "Installing $ncp_app"
(install)
Expand All @@ -208,6 +329,7 @@ function cleanup_script()
{
local script=$1
unset cleanup
# shellcheck source=/dev/null
source "$script"
if [[ $( type -t cleanup ) == function ]]; then
cleanup
Expand Down
27 changes: 21 additions & 6 deletions ncp-web/js/ncp.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ window.onpopstate = function(event) {
click_app($('#' + selectedID));
};

function errorMsg()
{
function errorMsg(e)
{
$('#config-box').fill( "Something went wrong. Try refreshing the page" );
}

Expand Down Expand Up @@ -268,21 +268,36 @@ $(function()
var ret = $.parseJSON( result );
if ( ret.token )
$('#csrf-token').set( { value: ret.token } );
if ( ret.ret ) // means that the process was launched
if ( "ret" in ret ) // means that the process was launched
{
if ( ret.ret == '0' )
if ( ret.ret == 0 )
{
if( ret.ref && ret.ref == 'nc-update' )
window.location.reload( true );
reload_sidebar();
$('.circle-retstatus').set('+icon-green-circle');
}
else
else if ( ret.ret === -1 ) // means we attach to an already running app
{
if( ret.output )
{
var box_l = $('#' + selectedID + '-details-box');
var box = box_l[0];
var lines = ret.output.split("\n");
lines.forEach(line => {
box_l.ht( box.innerHTML + escapeHTML(line) + '<br>' );
});
box.scrollTop = box.scrollHeight;
}
$('.circle-retstatus').set('-icon-green-circle');
}
else
{
$('.circle-retstatus').set('-icon-green-circle');
}
}
else // print error from server instead
{
$('.details-box').fill(ret.output);
$('.circle-retstatus').set('-icon-green-circle');
}
$( 'input' , '#config-box-wrapper' ).set('@disabled', null);
Expand Down
Loading