diff --git a/scripts/build.sh b/scripts/build.sh index b8bf0b0..24f94d7 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -44,12 +44,10 @@ while getopts ":Bt" opt; do t) IGNORE_TESTS=1 ;; :) - echo "Option -$OPTARG requires an argument." >&2 - exit 1 + echo_fatal -x "Option -$OPTARG requires an argument." ;; \?) - echo "Invalid option: -$OPTARG" >&2 - exit 1 + echo_fatal "Invalid option: -$OPTARG" ;; esac done @@ -63,61 +61,51 @@ initCargo rv=$(getVersion rustc 0.0) if ! versionAtLeast "$rv" "$RUSTC_MIN_VERSION"; then - echo "rustc not present or version less than $RUSTC_MIN_VERSION" - exit 1 + echo_fatal -x "rustc not present or version less than $RUSTC_MIN_VERSION" fi cv=$(getVersion cargo 0.0) if ! versionAtLeast "$cv" "$CARGO_MIN_VERSION"; then - echo "cargo not present or version less than $CARGO_MIN_VERSION" - exit 1 + echo_fatal -x "cargo not present or version less than $CARGO_MIN_VERSION" fi yv=$(getVersion yarn 0.0) if ! versionAtLeast "$yv" "$YARN_MIN_VERSION"; then - echo "yarn not present or version less than $YARN_MIN_VERSION" - exit 1 + echo_fatal -x "yarn not present or version less than $YARN_MIN_VERSION" fi # Building main server component # if [ "${FORCE_CLEAN:-0}" -eq 1 ]; then - echo "Forcing clean server build..."; echo + echo_info -x "Forcing clean server build..." cargo clean fi -echo "Building test version..."; echo +echo_info -x "Building test version..." if ! cargo test; then - echo "test failed." - echo "Try to run the following manually for more info" - echo "RUST_TEST_THREADS=1 cargo test --verbose" - echo + echo_error -x "test failed." "Try to run the following manually for more info" \ + "RUST_TEST_THREADS=1 cargo test --verbose" '' if [ "${IGNORE_TESTS:-0}" -ne 1 ]; then exit 1 fi fi if ! cargo build --release; then - echo "Server/release build failed." - echo "Try to run the following manually for more info" - echo "RUST_TEST_THREADS=1 cargo build --release --verbose" - echo + echo_error -x "Server/release build failed." "Try to run the following manually for more info" \ + "RUST_TEST_THREADS=1 cargo build --release --verbose" '' exit 1 fi # Building UI components # -echo "Building UI components..."; echo +echo_info -x "Building UI components..." if ! yarn build; then - echo "UI build failed." - echo "yarn build" - echo - exit 1 + echo_fatal -x "UI build failed." "yarn build" fi # Stop if build only is desired # if [ "${BUILD_ONLY:-0}" != 0 ]; then - echo "Build (only) complete, exiting"; echo + echo_info -x "Build (only) complete, exiting" exit 0 fi . `dirname ${BASH_SOURCE[0]}`/install.sh diff --git a/scripts/install.sh b/scripts/install.sh index 40a04e4..dcaf87e 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -44,22 +44,21 @@ while getopts ":s" opt; do s) NO_SERVICE=1 ;; :) - echo "Option -$OPTARG requires an argument." >&2 - exit 1 + echo_fatal "Option -$OPTARG requires an argument." ;; \?) - echo "Invalid option: -$OPTARG" >&2 - exit 1 + echo_fatal "Invalid option: -$OPTARG" ;; esac done +sudo_warn sudo install -m 755 target/release/moonfire-nvr ${SERVICE_BIN} if [ -x "${SERVICE_BIN}" ]; then - echo "Server Binary installed..."; echo + echo_info -x "Server Binary installed..." else - echo "Server build failed to install..."; echo + echo_info -x "Server build failed to install..." exit 1 fi if [ ! -d "${LIB_DIR}" ]; then @@ -69,32 +68,30 @@ if [ -d "ui-dist" ]; then sudo mkdir -p "${LIB_DIR}/ui" sudo cp -R ui-dist/. "${LIB_DIR}/ui/" sudo chown -R ${NVR_USER}:${NVR_GROUP} "${LIB_DIR}/ui/" - echo "Server UI installed..."; echo + echo_info -x "Server UI installed..." else - echo "Server UI failed to build or install..."; echo - exit 1 + echo_fatal -x "Server UI failed to build or install..." fi if [ "${NO_SERVICE:-0}" != 0 ]; then - echo "Not configuring systemctl service. Done"; echo + echo_info -x "Not configuring systemctl service. Done" exit 0 fi # Make sure user was created # if ! userExists "${NVR_USER}"; then - echo "NVR_USER=${NVR_USER} was not created. Do so manually" - echo "or run the setup script." - exit 1 + echo_fatal -x "NVR_USER=${NVR_USER} was not created. Do so manually or run the setup script." fi +pre_install_prep + # Prepare service files for socket when using priviliged port # SOCKET_SERVICE_PATH="/etc/systemd/system/${SERVICE_NAME}.socket" if [ $NVR_PORT -lt 1024 ]; then - echo_fatal "NVR_PORT ($NVR_PORT) < 1024: priviliged ports not supported" - exit 1 + echo_fatal -x "NVR_PORT ($NVR_PORT) < 1024: priviliged ports not supported" fi # Prepare service files for moonfire @@ -130,10 +127,10 @@ NVR_EOF # Configure and start service # if [ -f "${SERVICE_PATH}" ]; then - echo 'Configuring system daemon...'; echo + echo_info -x 'Configuring system daemon...' sudo systemctl daemon-reload sudo systemctl enable ${SERVICE_NAME} sudo systemctl restart ${SERVICE_NAME} - echo 'Getting system daemon status...'; echo + echo_info -x 'Getting system daemon status...' sudo systemctl status ${SERVICE_NAME} fi diff --git a/scripts/script-functions.sh b/scripts/script-functions.sh index a4b362d..5bae231 100755 --- a/scripts/script-functions.sh +++ b/scripts/script-functions.sh @@ -67,11 +67,78 @@ functionsInit() MOONFIRE_DIR="$(normalizeDirPath "`dirname "${p}"`/..")" } +read_lines() +{ + LINES_READ=() + while read -r line; do + LINES_READ+=("$line") + done +} + catPrefix() { sed -e "s/^/$2/" < "$1" } +mkdir_moonfire() +{ + sudo -u ${NVR_USER} -H mkdir "$@" +} + +echo_multi() +{ + local prefix='' + local plus='' + + while [[ $# -gt 0 ]]; do + case "$1" in + # Define a prefix for each line + -p) shift; prefix="$1"; shift ;; + # Provide extra empty line at end + -x) shift; plus=1 ;; + # Insert contents of LINES_READ here + # Only works as leading option + -L) shift; set -- "${LINES_READ[@]}" "$@" ;; + # Stop processing options + -) shift; break ;; + # Non option break out + *) break ;; + esac + done + + local A=("$@") + for l in "${A[@]/#/$prefix}"; do + echo "$l" + done + [ -n "$plus" ] && echo +} + +echo_stderr() +{ + echo_multi "$@" 1>&2 +} + +echo_info() +{ + echo_multi -x -p '>>> ' "$@" +} + + +echo_warn() +{ + echo_multi -p 'WARNING: ' "$@" 1>&2 +} + +echo_error() +{ + echo_multi -p 'ERROR: ' "$@" 1>&2 +} + +echo_fatal() +{ + echo_error "$@" + exit 1; +} # Read possible user config and then compute all derived environment @@ -90,7 +157,7 @@ initEnvironmentVars() NVR_HOME_BASE="${NVR_HOME_BASE:-/var/lib}" NVR_HOME="${NVR_HOME_BASE}/${NVR_USER}" DB_NAME="${DB_NAME:-db}" - DB_DIR="${DB_DIR:-$NVR_HOME}/${DB_NAME}" + DB_DIR="${DB_DIR:-$NVR_HOME/${DB_NAME}}" SAMPLE_FILE_DIR="${SAMPLE_FILE_DIR:-sample}" SAMPLE_MEDIA_DIR="${SAMPLE_MEDIA_DIR:-$NVR_HOME}" SERVICE_NAME="${SERVICE_NAME:-moonfire-nvr}" @@ -116,14 +183,15 @@ makePrepConfig() SERVICE_NAME=$SERVICE_NAME SERVICE_DESC="$SERVICE_DESC" EOF_CONFIG - echo "File prep.config newly created. Inspect and change as necessary." - echo "When done, re-run this setup script. Currently it contains:" + echo_info -x "File prep.config newly created. Inspect and change as necessary." \ + "When done, re-run this setup script. Currently it contains:" catPrefix "${MOONFIRE_DIR}/prep.config" " " + echo_info -x exit 0 else - echo "Setting up with variables:" + echo_info -x "Setting up with variables:" catPrefix "${MOONFIRE_DIR}/prep.config" " " - echo "" + echo_info -x fi } @@ -198,6 +266,98 @@ moonfire() esac } +sudo_warn() +{ + echo_warn -x -p '!!!!! ' \ + '------------------------------------------------------------------------------' \ + 'During this script you may be asked to input your root password' \ + 'This is for the purpose of using the sudo command and is necessary to complete' \ + 'the script successfully.' \ + '------------------------------------------------------------------------------' +} + + +# Prepare for sqlite directory and set schema into db +# +setup_db() +{ + DB_NAME=${1:-db} + if [ ! -d "${DB_DIR}" ]; then + echo_info -x 'Create database directory...' + mkdir_moonfire -p "${DB_DIR}" + fi + DB_PATH="${DB_DIR}/${DB_NAME}" + if [ ! -f "${DB_PATH}" ]; then + echo_info -x 'Create database and initialize...' + sudo -u "${NVR_USER}" -H sqlite3 "${DB_PATH}" < "${SRC_DIR}/schema.sql" + fi +} + +# Make sure all sample directories and files owned by moonfire +# +fix_ownership() +{ + sudo chown -R ${NVR_USER}.${NVR_USER} "$1" + echo_info -x "Fix ownership of files in \"$1\"..." +} + +# Make sure samples directory is ready +# +prep_sample_file_dir() +{ + if [ -z "${SAMPLE_MEDIA_DIR}" ]; then + echo_fatal -x "SAMPLE_MEDIA_DIR variable not configured. Check configuration." + exit 1 + fi + SAMPLE_FILE_PATH="${SAMPLE_MEDIA_DIR}/${SAMPLE_FILE_DIR}" + if [ "${SAMPLE_FILE_PATH##${NVR_HOME}}" != "${SAMPLE_FILE_PATH}" ]; then + # Under the home directory, create if not there + if [ ! -d "${SAMPLE_FILE_PATH}" ]; then + echo_info -x "Created sample file directory: \"$SAMPLE_FILE_PATH\"..." + mkdir_moonfire -p "${SAMPLE_FILE_PATH}" + fi + else + if [ ! -d "${SAMPLE_FILE_PATH}" ]; then + read_lines <<-MSG1 + Samples directory $SAMPLE_FILE_PATH does not exist. + If a mounted file system, make sure /etc/fstab is properly configured, + and file system is mounted and directory created. + MSG1 + echo_fatal -L + fi + fi + fix_ownership "${SAMPLE_FILE_PATH}" +} + +# Create user and groups if not there +# +prep_moonfire_user() +{ + echo_info -x "Create user/group and directories we need..." + if ! groupExists "${NVR_GROUP}"; then + sudo addgroup --quiet --system ${NVR_GROUP} + fi + if ! userExists "${NVR_USER}"; then + sudo adduser --quiet --system ${NVR_USER} \ + --ingroup "${NVR_GROUP}" --home "${NVR_HOME}" + fi + if [ ! -d "${NVR_HOME}" ]; then + mkdir_moonfire "${NVR_HOME}" + fi + sudo chown ${NVR_USER}:${NVR_GROUP} "${NVR_HOME}" +} + +# Correct possible timezone issues +# +fix_localtime() +{ + if [ ! -L /etc/localtime ] && [ -f /etc/timezone ] && + [ -f "/usr/share/zoneinfo/`cat /etc/timezone`" ]; then + echo_info -x "Correcting /etc/localtime setup issue..." + sudo ln -sf /usr/share/zoneinfo/`cat /etc/timezone` /etc/localtime + fi +} + # Add/update cameras in the database # # $1: path to cameras.sql file @@ -209,7 +369,7 @@ addCameras() { local cpath="${CAMERAS_PATH:-$1}" if [ -r "${cpath}" ]; then - echo 'Add cameras...'; echo + echo_info -x 'Add cameras...' # Before adding cameras, must stop service moonfire stop "${SERVICE_NAME:-$2}" >/dev/null 2>&1 sudo -u ${NVR_USER:-$3} -H sqlite3 "${DB_PATH:-$4}" < "${cpath}" @@ -217,20 +377,11 @@ addCameras() fi } -echo_stderr() +pre_install_prep() { - echo "$@" 1>&2 + prep_moonfire_user + setup_db db + prep_sample_file_dir + fix_localtime } -echo_warn() -{ - echo_stderr "WARNING: $@" - echo_stderr -} - -echo_fatal() -{ - echo_stderr "ERROR: $@" - echo_stderr - exit 1; -} diff --git a/scripts/setup-ubuntu.sh b/scripts/setup-ubuntu.sh index b7172bb..2c66f7c 100755 --- a/scripts/setup-ubuntu.sh +++ b/scripts/setup-ubuntu.sh @@ -44,17 +44,19 @@ while getopts ":f" opt; do f) DONT_BUILD_FFMPEG=1 ;; :) - echo_fatal "Option -$OPTARG requires an argument." >&2 + echo_fatal "Option -$OPTARG requires an argument." ;; \?) - echo_fatal "Invalid option: -$OPTARG" >&2 + echo_fatal -x "Invalid option: -$OPTARG" ;; esac done +sudo_warn + # Setup all apt packages we need # -echo 'Preparing and downloading packages we need...'; echo +echo_info -x 'Preparing and downloading packages we need...' PKGS="build-essential pkg-config sqlite3" #PKGS="$PKGS libavcodec-dev libavformat-dev libavutil-dev" PKGS="$PKGS libncurses5-dev libncursesw5-dev" @@ -94,6 +96,7 @@ if [ ${DO_UPDATE:-1} ]; then sudo apt-get update -y; fi # sudo apt-get install -y $PKGS sudo apt-get autoremove -y +echo_info -x # Check for ffmpeg and install by building if necessary # This needs to be done before building moonfire so it can @@ -103,17 +106,17 @@ ffv=`ffmpeg -version 2>/dev/null | extractVersion libavutil` ffv=${ffv:-0} if ! versionAtLeast "$ffv" "$FFMPEG_MIN_VERSION"; then if [ "${DONT_BUILD_FFMPEG:-0}" -ne 0 ]; then - echo "ffmpeg version (${ffv}) installed is too old for moonfire." - echo "Suggest you manually install at least version $FFMPEG_MIN_VERSION of libavutil." - echo "ffmpeg versions 2.x and 3.x all should work." + echo_warn -x "ffmpeg version (${ffv}) installed is too old for moonfire." \ + "Suggest you manually install at least version $FFMPEG_MIN_VERSION of libavutil." \ + "ffmpeg versions 2.x and 3.x all should work." else OLDDIR=`pwd` cd .. if [ -d FFmpeg ]; then - echo "Removing older FFmpeg directory..."; echo + echo_info -x "Removing older FFmpeg directory..." rm -fr FFmpeg fi - echo "Fetching FFmpeg source..."; echo + echo_info -x "Fetching FFmpeg source..." git clone --depth 1 -b "release/${FFMPEG_RELEASE_VERSION}" https://github.com/FFmpeg/FFmpeg.git cd FFmpeg pt=`uname -p 2>& /dev/null` @@ -128,7 +131,7 @@ if ! versionAtLeast "$ffv" "$FFMPEG_MIN_VERSION"; then OLDDIR= fi else - echo "FFmpeg is already usable..."; echo + echo_info -x "FFmpeg is already usable..." fi # If cargo appears installed, initialize for using it so rustc can be found @@ -138,23 +141,23 @@ initCargo # Make sure we have rust and cargo rv=$(getVersion rustc 0.0) if ! versionAtLeast "$rv" "$RUSTC_MIN_VERSION"; then - echo "Installing latest rust and cargo..."; echo + echo_info -x "Installing latest rust and cargo..." curl https://sh.rustup.rs -sSf | sh -s - -y initCargo fi cv=$(getVersion cargo "NA") if [ ${cv} = "NA" ]; then - echo "Cargo is not (properly) installed, but rust is." - echo "Suggest you install the latest rustup, or manually install cargo." - echo "Install using: curl https://sh.rustup.rs -sSf | sh -s -y" - exit 1 + echo_fatal -x "Cargo is not (properly) installed, but rust is." \ + "Suggest you install the latest rustup, or manually install cargo." + "Install using: curl https://sh.rustup.rs -sSf | sh -s -y" fi # Now make sure we have dev environment and tools for the UI portion # -echo "Installing all dependencies with yarn..." +echo_info -x "Installing all dependencies with yarn..." yarn install +echo_info -x finish() { @@ -164,45 +167,14 @@ finish() } trap finish EXIT -# Create user and groups if not there +# Rest of prep # -echo -echo "Create user/group and directories we need..."; echo -if ! groupExists "${NVR_GROUP}"; then - sudo addgroup --quiet --system ${NVR_GROUP} -fi -if ! userExists "${NVR_USER}"; then - sudo adduser --quiet --system ${NVR_USER} \ - --ingroup "${NVR_GROUP}" --home "${NVR_HOME}" -fi -if [ ! -d "${NVR_HOME}" ]; then - sudo mkdir "${NVR_HOME}" -fi -sudo chown ${NVR_USER}:${NVR_GROUP} "${NVR_HOME}" +pre_install_prep -# Correct possible timezone issues +# Initialize camera from sql file if present +# (DEPRECATED: Will be removed in future version # -echo "Correcting possible /etc/localtime setup issue..."; echo -if [ ! -L /etc/localtime ] && [ -f /etc/timezone ] && - [ -f "/usr/share/zoneinfo/`cat /etc/timezone`" ]; then - sudo rm /etc/localtime - sudo ln -s /usr/share/zoneinfo/`cat /etc/timezone` /etc/localtime -fi - - -# Prepare for sqlite directory and set schema into db -# -DB_NAME=db -DB_PATH="${DB_DIR}/${DB_NAME}" -if [ ! -d "${DB_DIR}" ]; then - echo 'Create database...'; echo - sudo -u "${NVR_USER}" -H mkdir "${DB_DIR}" -fi -if [ ! -f "${DB_PATH}" ]; then - sudo -u "${NVR_USER}" -H sqlite3 "${DB_PATH}" < "${SRC_DIR}/schema.sql" -fi - CAMERAS_PATH="${MOONFIRE_DIR}/cameras.sql" if [ ! -r "${CAMERAS_PATH}" ]; then CAMERAS_PATH="${MOONFIRE_DIR}/../cameras.sql" @@ -211,43 +183,15 @@ if [ ! -r "${CAMERAS_PATH}" ]; then fi fi if [ ! -z "${CAMERAS_PATH}" ]; then - echo "Adding camera confguration to db..."; echo + echo_warn "Camera configuration through sql file is deprecated and will not be supported in the future." \ + "Use \"moonfire-nvr config\" instead." + echo_info -x "Adding camera confguration to db..." addCameras else - echo_warn "No cameras auto configured. Use \"moonfire-nvr config\" to do it later..." + echo_warn -x "No cameras auto configured. Use \"moonfire-nvr config\" to do it later..." fi - -# Make sure samples directory is ready -# -if [ -z "${SAMPLE_MEDIA_DIR}" ]; then - echo "SAMPLE_MEDIA_DIR variable not configured. Check configuration." - exit 1 -fi -SAMPLE_FILE_PATH="${SAMPLE_MEDIA_DIR}/${SAMPLE_FILE_DIR}" -if [ "${SAMPLE_FILE_PATH##${NVR_HOME}}" != "${SAMPLE_FILE_PATH}" ]; then - # Under the home directory, create if not there - if [ ! -d "${SAMPLE_FILE_PATH}" ]; then - echo "Created samples directory: $SAMPLE_FILE_PATH"; echo - sudo -u ${NVR_USER} -H mkdir "${SAMPLE_FILE_PATH}" - fi -else - if [ ! -d "${SAMPLE_FILE_PATH}" ]; then - read -r -d '' MSG <<-MSG1 -Samples directory $SAMPLE_FILE_PATH does not exist. -If a mounted file system, make sure /etc/fstab is properly configured, -and file system is mounted and directory created. -MSG1 - echo_fatal "$MSG" - fi -fi -# Make sure all sample directories and files owned by moonfire -# -sudo chown -R ${NVR_USER}.${NVR_USER} "${SAMPLE_FILE_PATH}" -echo "Fix ownership of sample files..."; echo - - -cat <<-'INSTRUCTIONS' +read_lines <<-'INSTRUCTIONS' Unless there are errors above, everything you need should have been installed and you are now ready to build, install, and then use moonfire. @@ -255,3 +199,5 @@ Build by executing the script: scripts/build.sh Install by executing the script: scripts/install.sh (run automatically by build step). INSTRUCTIONS +echo_info -x -p ' ' -L +