diff --git a/containers/gluetun/scripts/gluetun_providers.sh b/containers/gluetun/scripts/gluetun_providers.sh index 0ba17a6..f1f0462 100644 --- a/containers/gluetun/scripts/gluetun_providers.sh +++ b/containers/gluetun/scripts/gluetun_providers.sh @@ -82,7 +82,7 @@ appWebuiRefresh_gluetun() { if [ -s "$tmp" ]; then runFileWrite "$output_file" < "$tmp"; rm -f "$tmp" - [[ -n "$new_etag" ]] && echo "$new_etag" | tee "$etag_file" >/dev/null + [[ -n "$new_etag" ]] && echo "$new_etag" | runFileWrite "$etag_file" isSuccessful "Refreshed gluetun provider snapshot ($(jq '.providers | length' "$output_file") providers)." else rm -f "$tmp" diff --git a/containers/grafana/scripts/grafana_install_hooks.sh b/containers/grafana/scripts/grafana_install_hooks.sh index cfa2a26..79467b4 100644 --- a/containers/grafana/scripts/grafana_install_hooks.sh +++ b/containers/grafana/scripts/grafana_install_hooks.sh @@ -17,7 +17,7 @@ grafana_install_post_start() local app_name="$1" if [ -d "${containers_dir}grafana/grafana_storage" ]; then local result - result=$(sudo chmod -R 777 "${containers_dir}grafana/grafana_storage") + result=$(runFileOp chmod -R 777 "${containers_dir}grafana/grafana_storage") checkSuccess "Set permissions to grafana_storage folder." fi } diff --git a/containers/prometheus/scripts/prometheus_install_hooks.sh b/containers/prometheus/scripts/prometheus_install_hooks.sh index 00588fa..ec0752e 100644 --- a/containers/prometheus/scripts/prometheus_install_hooks.sh +++ b/containers/prometheus/scripts/prometheus_install_hooks.sh @@ -28,12 +28,12 @@ prometheus_install_post_start() fi if [ -d "${containers_dir}prometheus/prometheus" ]; then local result - result=$(sudo chmod -R 777 "${containers_dir}prometheus/prometheus") + result=$(runFileOp chmod -R 777 "${containers_dir}prometheus/prometheus") checkSuccess "Set permissions to prometheus folder." fi if [ -d "${containers_dir}prometheus/prom_data" ]; then local result - result=$(sudo chmod -R 777 "${containers_dir}prometheus/prom_data") + result=$(runFileOp chmod -R 777 "${containers_dir}prometheus/prom_data") checkSuccess "Set permissions to prom_data folder." fi } diff --git a/scripts/cli/commands/updater/cli_updater_commands.sh b/scripts/cli/commands/updater/cli_updater_commands.sh index 6ceeb94..6478c7b 100644 --- a/scripts/cli/commands/updater/cli_updater_commands.sh +++ b/scripts/cli/commands/updater/cli_updater_commands.sh @@ -156,13 +156,13 @@ updaterRecordHistory() local app="$1" action="$2" from="$3" to="$4" result="$5" local f="$containers_dir/libreportal/frontend/data/updater/generated/history.json" command -v jq >/dev/null 2>&1 || return 0 - [ -f "$f" ] || printf '{ "entries": [] }\n' > "$f" + [ -f "$f" ] || printf '{ "entries": [] }\n' | runFileWrite "$f" local ts; ts="$(date -Iseconds 2>/dev/null || date)" local tmp; tmp="$(mktemp)" if jq --arg ts "$ts" --arg app "$app" --arg action "$action" --arg from "$from" --arg to "$to" --arg result "$result" \ '.entries = ([{ts:$ts, app:$app, action:$action, from:$from, to:$to, result:$result}] + (.entries // []))[0:200]' \ "$f" > "$tmp" 2>/dev/null; then - runFileOp cp "$tmp" "$f" 2>/dev/null || cp "$tmp" "$f" + runFileWrite "$f" < "$tmp" fi rm -f "$tmp" } diff --git a/scripts/config/core/variables/config_scan_variables.sh b/scripts/config/core/variables/config_scan_variables.sh index 2ef4774..b38dfb9 100755 --- a/scripts/config/core/variables/config_scan_variables.sh +++ b/scripts/config/core/variables/config_scan_variables.sh @@ -86,8 +86,8 @@ reconcileConfigFile() # Replace only when the result is sane (non-empty, has keys) and differs. if [[ -s "$tmp" ]] && grep -q '^CFG_' "$tmp" && ! runInstallOp cmp -s "$tmp" "$live"; then - runInstallOp cp -a "$live" "${live}.bak" - runInstallOp cp "$tmp" "$live" + runCfgOp cp -a "$live" "${live}.bak" + { [[ -n "$containers_dir" && "$live" == "$containers_dir"* ]] && runFileWrite "$live" < "$tmp" || runInstallOp cp "$tmp" "$live"; } isSuccessful "Reconciled config: $(basename "$live") (backup: $(basename "$live").bak)" fi rm -f "$tmp" diff --git a/scripts/function/permission/ownership/folder_group.sh b/scripts/function/permission/ownership/folder_group.sh index 8e366fb..90ea65e 100755 --- a/scripts/function/permission/ownership/folder_group.sh +++ b/scripts/function/permission/ownership/folder_group.sh @@ -27,13 +27,13 @@ changeUserGroupOnFolder() checkSuccess "Updating $directory user to be $target_user... This may take a while..." # Check if the source group exists - local source_group=$(id -g -n "$source_user") + local source_group; source_group=$(id -g -n "$source_user") if [ $? -ne 0 ]; then isError "Unable to determine source group for user '$source_user'." fi # Check if the target group exists - local target_group=$(id -g -n "$target_user") + local target_group; target_group=$(id -g -n "$target_user") if [ $? -ne 0 ]; then isError "Unable to determine target group for user '$target_user'." fi diff --git a/scripts/network/ip/ip_find_available.sh b/scripts/network/ip/ip_find_available.sh index f1fcfd4..d717083 100755 --- a/scripts/network/ip/ip_find_available.sh +++ b/scripts/network/ip/ip_find_available.sh @@ -8,7 +8,7 @@ ipFindAvailable() local start_last=2 # Hardcoded sensible default: .2 local end_last=254 # Hardcoded sensible default: .254 - local existing_ips=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM network_resources WHERE resource_type = 'ip' AND status = 'active';" 2>/dev/null) + local existing_ips; existing_ips=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM network_resources WHERE resource_type = 'ip' AND status = 'active';" 2>/dev/null) if [[ $? -ne 0 ]]; then isError "Database query failed while checking existing IPs" available_ip="" diff --git a/scripts/peer/peer_pull.sh b/scripts/peer/peer_pull.sh index 7e007cb..81f1e2a 100644 --- a/scripts/peer/peer_pull.sh +++ b/scripts/peer/peer_pull.sh @@ -84,7 +84,7 @@ peerPullApp() # of the flow on a partial extract. ( set -o pipefail - peerExec "$peer_name" "stream-app $app" | tar -C "$containers_dir" -xf - + peerExec "$peer_name" "stream-app $app" | runFileOp tar -C "$containers_dir" -xf - ) local transfer_rc=$? if (( transfer_rc != 0 )); then diff --git a/scripts/task/crontab_check_processor.sh b/scripts/task/crontab_check_processor.sh index 48a310b..5ad0875 100755 --- a/scripts/task/crontab_check_processor.sh +++ b/scripts/task/crontab_check_processor.sh @@ -71,25 +71,25 @@ HEALTH_REPORT_FILE="$TASK_DIR/health_report.json" healthLogInfo() { local message="$1" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') - echo "$timestamp [INFO] [HEALTH_CHECK] $message" | tee -a "$HEALTH_LOG_FILE" + echo "$timestamp [INFO] [HEALTH_CHECK] $message" | runFileWrite -a "$HEALTH_LOG_FILE" } healthLogError() { local message="$1" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') - echo "$timestamp [ERROR] [HEALTH_CHECK] $message" | tee -a "$HEALTH_LOG_FILE" + echo "$timestamp [ERROR] [HEALTH_CHECK] $message" | runFileWrite -a "$HEALTH_LOG_FILE" } healthLogWarning() { local message="$1" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') - echo "$timestamp [WARN] [HEALTH_CHECK] $message" | tee -a "$HEALTH_LOG_FILE" + echo "$timestamp [WARN] [HEALTH_CHECK] $message" | runFileWrite -a "$HEALTH_LOG_FILE" } healthLogSuccess() { local message="$1" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') - echo "$timestamp [SUCCESS] [HEALTH_CHECK] $message" | tee -a "$HEALTH_LOG_FILE" + echo "$timestamp [SUCCESS] [HEALTH_CHECK] $message" | runFileWrite -a "$HEALTH_LOG_FILE" } # ======================================== @@ -673,11 +673,11 @@ performMaintenance() { healthLogInfo "Performing system maintenance..." # Clean up old logs - find "$TASK_DIR" -name "*.log" -mtime +7 -delete 2>/dev/null + runFileOp find "$TASK_DIR" -name "*.log" -mtime +7 -delete 2>/dev/null # Clean up temporary files - find "$TASK_DIR" -name "*.tmp" -delete 2>/dev/null - find "$TASK_DIR" -name ".queue.*" -delete 2>/dev/null + runFileOp find "$TASK_DIR" -name "*.tmp" -delete 2>/dev/null + runFileOp find "$TASK_DIR" -name ".queue.*" -delete 2>/dev/null # Rotate large logs for logFile in "$TASK_DIR"/*.log; do diff --git a/scripts/webui/data/generators/apps/webui_config.sh b/scripts/webui/data/generators/apps/webui_config.sh index 2bc2abd..89ea809 100644 --- a/scripts/webui/data/generators/apps/webui_config.sh +++ b/scripts/webui/data/generators/apps/webui_config.sh @@ -164,7 +164,7 @@ EOF if [[ -n "$icon_file" ]]; then local icons_apps_dir="${containers_dir}libreportal/frontend/core/icons/apps" runFileOp mkdir -p "$icons_apps_dir" - cp "$dir/$icon_file" "$icons_apps_dir/$icon_file" 2>/dev/null + runFileWrite "$icons_apps_dir/$icon_file" < "$dir/$icon_file" 2>/dev/null fi # Service names — one awk pass instead of 9 grep|awk|head pipelines. diff --git a/scripts/webui/data/generators/backup/webui_task_create.sh b/scripts/webui/data/generators/backup/webui_task_create.sh index a9b6a9c..c8e0e20 100755 --- a/scripts/webui/data/generators/backup/webui_task_create.sh +++ b/scripts/webui/data/generators/backup/webui_task_create.sh @@ -16,16 +16,16 @@ createTaskFile() { # Set task directory local task_dir="${containers_dir}libreportal/frontend/data/tasks" - # Ensure task directory exists + # Ensure task directory exists (container-owned WebUI data tree -> runFileOp) if [ ! -d "$task_dir" ]; then - mkdir -p "$task_dir" - chown -R $docker_install_user:$docker_install_user "$task_dir" + runFileOp mkdir -p "$task_dir" + runFileOp chown -R $docker_install_user:$docker_install_user "$task_dir" fi # Ensure queue.json exists if [ ! -f "$task_dir/queue.json" ]; then - echo "[]" | tee "$task_dir/queue.json" >/dev/null - chown $docker_install_user:$docker_install_user "$task_dir/queue.json" + echo "[]" | runFileWrite "$task_dir/queue.json" + runFileOp chown $docker_install_user:$docker_install_user "$task_dir/queue.json" fi # Generate unique task ID @@ -55,26 +55,26 @@ createTaskFile() { task_json+="}" - # Write task file - echo "$task_json" | tee "$task_file" >/dev/null - chown $docker_install_user:$docker_install_user "$task_file" + # Write task file (container-owned -> runFileWrite tees as the install user) + echo "$task_json" | runFileWrite "$task_file" + runFileOp chown $docker_install_user:$docker_install_user "$task_file" # Add task ID to queue.json local queue_content=$(cat "$task_dir/queue.json" 2>/dev/null) - + if command -v jq >/dev/null 2>&1; then # Use jq if available - echo "$queue_content" | jq --arg task "$task_id" '. + [$task]' | tee "$task_dir/queue.json" >/dev/null + echo "$queue_content" | jq --arg task "$task_id" '. + [$task]' | runFileWrite "$task_dir/queue.json" else # Fallback: manual JSON manipulation if [ "$queue_content" = "[]" ]; then - echo "[\"$task_id\"]" | tee "$task_dir/queue.json" >/dev/null + echo "[\"$task_id\"]" | runFileWrite "$task_dir/queue.json" else - echo "$queue_content" | sed 's/\]$/,\n"'$task_id'"]/' | tee "$task_dir/queue.json" >/dev/null + echo "$queue_content" | sed 's/\]$/,\n"'$task_id'"]/' | runFileWrite "$task_dir/queue.json" fi fi - chown $docker_install_user:$docker_install_user "$task_dir/queue.json" + runFileOp chown $docker_install_user:$docker_install_user "$task_dir/queue.json" isSuccessful "Task created: $task_id" } diff --git a/scripts/webui/data/generators/system/webui_system_metrics.sh b/scripts/webui/data/generators/system/webui_system_metrics.sh index 8d003fb..598de5e 100644 --- a/scripts/webui/data/generators/system/webui_system_metrics.sh +++ b/scripts/webui/data/generators/system/webui_system_metrics.sh @@ -232,7 +232,7 @@ webuiSystemAppStorage() { if [[ -z "$ids" ]]; then printf '{"apps":[],"total":0,"total_local":0,"total_external":0,"updated":"%s"}\n' "$now_iso" \ | runFileWrite "$final_file" - runAsManager touch "$stamp_file" 2>/dev/null || touch "$stamp_file" 2>/dev/null + runFileOp touch "$stamp_file" 2>/dev/null || true return 0 fi @@ -297,7 +297,7 @@ webuiSystemAppStorage() { runFileWrite "$final_file" < "$tmp" fi rm -f "$tmp" - runAsManager touch "$stamp_file" 2>/dev/null || touch "$stamp_file" 2>/dev/null + runFileOp touch "$stamp_file" 2>/dev/null || true } # Per-app Docker resource snapshot, grouped by compose project. Apps without a diff --git a/scripts/webui/data/generators/system/webui_system_update.sh b/scripts/webui/data/generators/system/webui_system_update.sh index 2bbb221..f076cb6 100755 --- a/scripts/webui/data/generators/system/webui_system_update.sh +++ b/scripts/webui/data/generators/system/webui_system_update.sh @@ -120,7 +120,7 @@ EOF local _lv; _lv=$(lpReleaseLatestVersion 2>/dev/null) if [[ -n "$_lv" ]]; then latest_version="$_lv" - runAsManager touch "$stamp_file" 2>/dev/null || touch "$stamp_file" 2>/dev/null + runFileOp touch "$stamp_file" 2>/dev/null || true # Does the published release bump the root-owned footprint? If so, # applying it needs a root re-install, not a WebUI `update apply`. if declare -f lpReleaseLatestFootprint >/dev/null 2>&1; then @@ -192,7 +192,7 @@ EOF fi if [[ "$_fetched" == "true" ]]; then - runAsManager touch "$stamp_file" 2>/dev/null || touch "$stamp_file" 2>/dev/null + runFileOp touch "$stamp_file" 2>/dev/null || true else fetch_error="Could not reach the update server." fi @@ -260,7 +260,7 @@ webuiSystemVerify() { declare -f lpVerifyInstall >/dev/null 2>&1 || return 0 lpVerifyInstall - runAsManager touch "$stamp_file" 2>/dev/null || touch "$stamp_file" 2>/dev/null + runFileOp touch "$stamp_file" 2>/dev/null || true # Encode the sample-paths array (each path JSON-escaped). local sample_json="[]" diff --git a/scripts/webui/data/lock/webui_remove_setup_lock.sh b/scripts/webui/data/lock/webui_remove_setup_lock.sh index c5eb278..983cf88 100755 --- a/scripts/webui/data/lock/webui_remove_setup_lock.sh +++ b/scripts/webui/data/lock/webui_remove_setup_lock.sh @@ -7,6 +7,6 @@ webuiRemoveSetupLock() { local lock_file="$containers_dir/libreportal/frontend/data/setup.lock" if [ -f "$lock_file" ]; then - rm "$lock_file" + runFileOp rm -f "$lock_file" fi } diff --git a/scripts/webui/data/utils/webui_app_icons.sh b/scripts/webui/data/utils/webui_app_icons.sh index 570a6f0..da00bb7 100755 --- a/scripts/webui/data/utils/webui_app_icons.sh +++ b/scripts/webui/data/utils/webui_app_icons.sh @@ -14,7 +14,7 @@ webuiSyncAppIcon() { [[ -z "$app_name" ]] && return 1 local icons_dir="${containers_dir}libreportal/frontend/core/icons/apps" - mkdir -p "$icons_dir" + runFileOp mkdir -p "$icons_dir" # Icons live in the install template dir — copy_build_context.sh # excludes *.svg from the install→deployed copy, so the deployed @@ -27,8 +27,8 @@ webuiSyncAppIcon() { # cp to a temp name then mv so the webserver never serves a # half-written file. local dest="${icons_dir}/${app_name}.${ext}" - if cp "$src" "${dest}.tmp.$$" 2>/dev/null; then - mv "${dest}.tmp.$$" "$dest" 2>/dev/null + if runFileWrite "${dest}.tmp.$$" < "$src" 2>/dev/null; then + runFileOp mv "${dest}.tmp.$$" "$dest" 2>/dev/null fi return 0 fi