Bash script exits prematurely when calling another script inside it
1
vote
2
answers
151
views
I am trying to run a script which calls another script, but it does not seem to return to the script that called it.
The source script "backup-plex.sh" calls “Linux_Plex_Backup.sh” (whilst passing an argument for the destination path).
Once the script “Linux_Plex_Backup.sh” has been completed it should return to the original script "backup-plex.sh" and continue with the rsync command, but it doesn’t.
I call the source script using:
~/.backupScripts/./backup-plex.sh
Below is the source script which calls the script “Linux_Plex_Backup.sh” :
#!/bin/bash
# Define source path
source=/media/plex1
# Define destination paths
destination=/media/backPlex1ON
dest_plex_library=PlexLibraryBackup
echo "********************* Performing backup of Plex Media Library *********************"
# call plex library backup script
sudo -s ~/.backupScripts/PlexBackup/Linux_Plex_Backup.sh $destination/$dest_plex_library
echo "********************* Performing rsync backup of Plex 1 *********************"
# rsync command excludes
rsync_excludes="--exclude '*.ini' \
--exclude '*.DS_Store' \
--exclude '*._*' \
--exclude '**/\$RECYCLE.BIN' \
--exclude '**/\lost+found' \
--exclude '*.AppleDouble' \
--exclude '*.localized' \
--exclude '*.Trash-1000' \
--exclude '**/\PlexLibraryBackup'"
# rsync command options
rsync_cmd="/usr/local/bin/rsync"
rsync_options="-a --progress -l --delete $rsync_excludes"
eval $rsync_cmd $rsync_options $source $destination
Below is the “Linux_Plex_Backup.sh” script called by the source script …
#!/usr/bin/env bash
# shellcheck disable=SC2317,SC2181
#--------------------------------------------------------------------------
# Backup Linux Plex Database to tgz file in Backup folder.
# v1.1.6 04-Nov-2024 007revad
#
# MUST be run by a user in sudo, sudoers or wheel group, or as root
#
# To run the script:
# sudo -i /share/scripts/backup_linux_plex_to_tar.sh
# Change /share/scripts/ to the path where this script is located
#
# To do a test run on just Plex's profiles folder run:
# sudo -i /share/scripts/backup_linux_plex_to_tar.sh test
# Change /share/scripts/ to the path where this script is located
#
# Github: https://github.com/007revad/Linux_Plex_Backup
# Script verified at https://www.shellcheck.net/
#--------------------------------------------------------------------------
scriptver="v1.1.6"
script=Linux_Plex_Backup
if [ -z $1 ] ; then
echo "Argument missing: define destination path"
exit
fi
# Read variables from backup_linux_plex.config
Backup_Directory="$1" # JL: backup directory is passed as a parameter ($1) when Linux_Plex_Backup script is called
Name=""
LogAll=""
KeepQty=""
if [[ -f $(dirname -- "$0";)/backup_linux_plex.config ]];then
# shellcheck disable=SC1090,SC1091
while read -r var; do
if [[ $var =~ ^[a-zA-Z0-9_]+=.* ]]; then export "$var"; fi
done > "${Log_File}"
echo -e "$(basename -- "${Err_Log_File}")\n" |& tee -a "${Log_File}"
else
# Log and notify of backup success
echo -e "\nPlex backup completed successfully" |& tee -a "${Log_File}"
fi
exit "${arg1}"
}
trap cleanup EXIT
#--------------------------------------------------------------------------
# Check that script is running as root
if [[ $( whoami ) != "root" ]]; then
if [[ -d $Backup_Directory ]]; then
echo "ERROR: This script must be run as root!" |& tee -a "${Tmp_Err_Log_File}"
echo "ERROR: $( whoami ) is not root. Aborting." |& tee -a "${Tmp_Err_Log_File}"
else
# Can't log error to log file because $Backup_Directory does not exist
echo -e "\nERROR: This script must be run as root!"
echo -e "ERROR: $( whoami ) is not root. Aborting.\n"
fi
# Abort script because it isn't being run by root
exit 255
fi
#--------------------------------------------------------------------------
# "Plex Media Server" folder location
# ADM /volume1/Plex/Library/Plex Media Server
# DSM6 /volume1/Plex/Library/Application Support/Plex Media Server
# DSM7 /volume1/PlexMediaServer/AppData/Plex Media Server
# Linux /var/lib/plexmediaserver/Library/Application Support/Plex Media Server
# Set the Plex Media Server data location
Plex_Data_Path="/var/lib/plexmediaserver/Library/Application Support"
#--------------------------------------------------------------------------
# Check Plex Media Server data path exists
if [[ ! -d $Plex_Data_Path ]]; then
echo "Plex Media Server data path invalid! Aborting." |& tee -a "${Tmp_Err_Log_File}"
echo "${Plex_Data_Path}" |& tee -a "${Tmp_Err_Log_File}"
# Abort script because Plex data path invalid
exit 255
fi
#--------------------------------------------------------------------------
# Get Plex Media Server version
Version="$(/usr/lib/plexmediaserver/Plex\ Media\ Server --version)"
# Returns v1.29.2.6364-6d72b0cf6
# Plex version without v or hex string
Version=$(printf %s "${Version:1}"| cut -d "-" -f1)
# Returns 1.29.2.6364
#--------------------------------------------------------------------------
# Re-assign log names to include Plex version
# Backup filename
Backup_Name="${Nas}"_"${Now}"_Plex_"${Version}"_Backup
# If file exists already include time in name
BackupPN="$Backup_Directory/$Backup_Name"
if [[ -f $BackupPN.tgz ]] || [[ -f $BackupPN.log ]] || [[ -f "$BackupPN"_ERROR.log ]]; then
Backup_Name="${Nas}"_"${NowLong}"_Plex_"${Version}"_Backup
fi
# Log file filename
Log_File="${Backup_Directory}"/"${Backup_Name}".log
# Error log filename
Err_Log_File="${Backup_Directory}"/"${Backup_Name}"_ERROR.log
#--------------------------------------------------------------------------
# Start logging
echo -e "$script $scriptver\n" |& tee -a "${Log_File}"
# Log Linux distro, version and hostname
Distro="$(uname -a | awk '{print $2}')"
DistroVersion="$(uname -a | awk '{print $3}' | cut -d"-" -f1)"
echo "${Distro}" "${DistroVersion}" |& tee -a "${Log_File}"
echo "Hostname: $( hostname )" |& tee -a "${Log_File}"
# Log Plex version
echo Plex version: "${Version}" |& tee -a "${Log_File}"
#--------------------------------------------------------------------------
# Check if backup directory exists
if [[ ! -d $Backup_Directory ]]; then
echo "ERROR: Backup directory not found! Aborting backup." |& tee -a "${Log_File}" "${Tmp_Err_Log_File}"
# Abort script because backup directory not found
exit 255
fi
#--------------------------------------------------------------------------
# Stop Plex Media Server
echo "Stopping Plex..." |& tee -a "${Log_File}"
Result=$(systemctl stop plexmediaserver)
code="$?"
# Give sockets a moment to close
sleep 5
if [[ $code == "0" ]]; then
echo "Plex Media Server has stopped." |& tee -a "$Log_File"
else
echo "$Result" |& tee -a "$Log_File"
exit $code
fi
# Nicely terminate any residual Plex processes (plug-ins, tuner service and EAE etc)
###pgrep [Pp]lex | xargs kill -15 &>/dev/null
# Give sockets a moment to close
###sleep 5
# Kill any residual processes which DSM did not clean up (plug-ins and EAE)
Pids="$(ps -ef | grep -i 'plex plug-in' | grep -v grep | awk '{print $2}')"
[ "$Pids" != "" ] && kill -9 "$Pids"
Pids="$(ps -ef | grep -i 'plex eae service' | grep -v grep | awk '{print $2}')"
[ "$Pids" != "" ] && kill -9 "$Pids"
Pids="$(ps -ef | grep -i 'plex tuner service' | grep -v grep | awk '{print $2}')"
[ "$Pids" != "" ] && kill -9 "$Pids"
# Give sockets a moment to close
sleep 2
#--------------------------------------------------------------------------
# Check if all Plex processes have stopped
echo Checking status of Plex processes... |& tee -a "${Log_File}"
Response=$(pgrep -l plex)
# Check if plexmediaserver was found in $Response
if [[ -n $Response ]]; then
# Forcefully kill any residual Plex processes (plug-ins, tuner service and EAE etc)
pgrep [Pp]lex | xargs kill -9 &>/dev/null
sleep 5
# Check if plexmediaserver still found in $Response
Response=$(pgrep -l plex)
if [[ -n $Response ]]; then
echo "ERROR: Some Plex processes still running! Aborting backup."\
|& tee -a "${Log_File}" "${Tmp_Err_Log_File}"
echo "${Response}" |& tee -a "${Log_File}" "${Tmp_Err_Log_File}"
# Start Plex to make sure it's not left partially running
/usr/lib/plexmediaserver/Resources/start.sh
# Abort script because Plex didn't shut down fully
exit 255
else
echo "All Plex processes have stopped." |& tee -a "${Log_File}"
fi
else
echo "All Plex processes have stopped." |& tee -a "${Log_File}"
fi
#--------------------------------------------------------------------------
# Backup Plex Media Server
echo "=================================================" |& tee -a "${Log_File}"
echo "Backing up Plex Media Server data files..." |& tee -a "${Log_File}"
Exclude_File="$( dirname -- "$0"; )/plex_backup_exclude.txt"
# Check for test or error arguments
if [[ -n $1 ]] && [[ ${1,,} == "error" ]]; then
# Trigger an error to test error logging
Test="Plex Media Server/Logs/ERROR/"
echo "Running small error test backup of Logs folder" |& tee -a "${Log_File}"
elif [[ -n $1 ]] && [[ ${1,,} == "test" ]]; then
# Test on small Logs folder only
Test="Plex Media Server/Logs/"
echo "Running small test backup of Logs folder" |& tee -a "${Log_File}"
fi
# Check if exclude file exists
# Must come after "Check for test or error arguments"
if [[ -f $Exclude_File ]]; then
# Unset arguments
while [[ $1 ]]; do shift; done
# Set -X excludefile arguments for tar
set -- "$@" "-X"
set -- "$@" "${Exclude_File}"
else
echo "INFO: No exclude file found." |& tee -a "${Log_File}"
fi
# Use short variable names so tar command is not too long
BD="${Backup_Directory}"
BN="${Backup_Name}"
PDP="${Plex_Data_Path}"
LF="${Log_File}"
TELF="${Tmp_Err_Log_File}"
PMS="Plex Media Server"
# Run tar backup command
if [[ -n $Test ]]; then
# Running backup test or error test
if [[ ${LogAll,,} == "yes" ]]; then
echo "Logging all archived files" |& tee -a "${Log_File}"
tar -cvpzf "${BD}"/"${BN}".tgz -C "${PDP}" "${Test}" > >(tee -a "${LF}") 2> >(tee -a "${LF}" "${TELF}" >&2)
else
# Don't log all backed up files.
echo "Only logging errors" |& tee -a "${Log_File}"
tar -cvpzf "${BD}"/"${BN}".tgz -C "${PDP}" "${Test}" 2> >(tee -a "${LF}" "${TELF}" >&2)
fi
else
# Backup to tgz with PMS version and date in file name, send all output to shell and log, plus errors to error.log
# Using -C to change directory to "/share/Plex/Library/Application Support" to not backup absolute path
# and avoid "tar: Removing leading /" error
if [[ ${LogAll,,} == "yes" ]]; then
echo "Logging all archived files" |& tee -a "${Log_File}"
tar -cvpzf "${BD}"/"${BN}".tgz "$@" -C "${PDP}" "$PMS/" > >(tee -a "${LF}") 2> >(tee -a "${LF}" "${TELF}" >&2)
else
# Don't log all backed up files.
echo "Only logging errors" |& tee -a "${Log_File}"
tar -cvpzf "${BD}"/"${BN}".tgz "$@" -C "${PDP}" "$PMS/" 2> >(tee -a "${LF}" "${TELF}" >&2)
fi
fi
echo "Finished backing up Plex Media Server data files." |& tee -a "${Log_File}"
echo "=================================================" |& tee -a "${Log_File}"
#--------------------------------------------------------------------------
# Start Plex Media Server
echo "Starting Plex..." |& tee -a "${Log_File}"
#/usr/lib/plexmediaserver/Resources/start.sh
systemctl start plexmediaserver
#--------------------------------------------------------------------------
# Delete old backups
if [[ $KeepQty -gt "0" ]]; then
readarray -t array < <(ls "$Backup_Directory" |\
grep -E "${Nas}"'_[0-9]{8,}(-[0-9]{4,})?_Plex_.*\.tgz' | head -n -"$KeepQty")
if [[ "${#array[@]}" -gt "0" ]]; then
echo -e "\nDeleting old backups" |& tee -a "${Log_File}"
for file in "${array[@]}"; do
if [[ -f "$Backup_Directory/$file" ]]; then
echo "Deleting $file" |& tee -a "${Log_File}"
rm "$Backup_Directory/$file"
fi
if [[ -f "$Backup_Directory/${file%.tgz}.log" ]]; then
echo "Deleting ${file%.tgz}.log" |& tee -a "${Log_File}"
rm "$Backup_Directory/${file%.tgz}.log"
fi
if [[ -f "$Backup_Directory/${file%.tgz}_ERROR.log" ]]; then
echo "Deleting ${file%.tgz}_ERROR.log" |& tee -a "${Log_File}"
rm "$Backup_Directory/${file%.tgz}_ERROR.log"
fi
done
fi
fi
#--------------------------------------------------------------------------
# Append the time taken to stdout and log file
# End Time and Date
Finished=$( date )
# bash timer variable to log time taken to backup Plex
end="${SECONDS}"
# Elapsed time in seconds
Runtime=$(( end - start ))
# Append start and end date/time and runtime
echo -e "\nBackup Started: " "${Started}" |& tee -a "${Log_File}"
echo "Backup Finished:" "${Finished}" |& tee -a "${Log_File}"
# Append days, hours, minutes and seconds from $Runtime
printf "Backup Duration: " |& tee -a "${Log_File}"
printf '%dd:%02dh:%02dm:%02ds\n' \
$((Runtime/86400)) $((Runtime%86400/3600)) $((Runtime%3600/60))\
$((Runtime%60)) |& tee -a "${Log_File}"
#--------------------------------------------------------------------------
# Trigger cleanup function
exit 0
After running the scripts, the terminal window shows this...
Finished backing up Plex Media Server data files.
=================================================
Starting Plex...
Backup Started: Wed 8 Jan 09:29:21 GMT 2025
Backup Finished: Wed 8 Jan 09:33:17 GMT 2025
Backup Duration: 0d:00h:03m:56s
Plex backup completed successfully
username@homeserver:~$
In fact I have to press enter to get back to the command prompt, because it stays at " Plex backup completed successfully" until I press enter (is this a clue to the issue ?).
If the source script continued to run then I would expect to see the echo string (shown below) and the rsync command.
********************* Performing rsync backup of Plex 1 *********************"
Or is the issue anything to do with the fact that the source script starts with:
#!/bin/bash
and the script that's called starts with:
#!/usr/bin/env bash
UPDATE 08/01/25: I stripped most of “Linux_Plex_Backup.sh” to simplify it and it returns to the source script to run rsync. So there is something in “Linux_Plex_Backup.sh” thats causing the problem. The script was written by someone else and more advanced than my bash skills, so Im not sure whats causing it.
I tried commenting out "trap cleanup EXIT" as suggested but in made no difference
Asked by John
(47 rep)
Jan 7, 2025, 08:38 PM
Last activity: Jan 14, 2025, 01:42 PM
Last activity: Jan 14, 2025, 01:42 PM