If you want to implement the same script, create a file in /var/local/bin/ as below
/usr/local/bin/lxc_updater.sh
#!/bin/bash
# Define log file
LOGFILE="/var/log/lxc_update.log"
# Check if the script is running in an interactive terminal
if [ -t 1 ]; then
# If interactive, output to both terminal and log file
LOG_OUTPUT_MODE="TEE"
echo "Running in interactive mode. Output will be shown in terminal and logged."
else
# If not interactive (cron job), redirect all output to the log file
LOG_OUTPUT_MODE="SILENT"
exec 1>>$LOGFILE 2>&1
fi
# Add a function to handle logging based on the mode
log_message() {
local message="$1"
if [ "$LOG_OUTPUT_MODE" == "TEE" ]; then
echo "$message" | tee -a "$LOGFILE"
else
echo "$message"
fi
}
# Use full path for lxc commands
LXC_LS_CMD="/usr/bin/lxc-ls"
LXC_ATTACH_CMD="/usr/bin/lxc-attach"
LXC_STOP_CMD="/usr/bin/lxc-stop"
LXC_START_CMD="/usr/bin/lxc-start"
# Add timestamp
log_message "---------------------------------------------------"
log_message "LXC container update started on $(date)"
log_message "---------------------------------------------------"
# Get a list of all running LXC containers
CONTAINERS_LIST=$($LXC_LS_CMD -f | grep 'RUNNING' | awk '{print $1}')
if [ -z "$CONTAINERS_LIST" ]; then
log_message "No running LXC containers found. Exiting."
exit 0
fi
# Loop through each running container using a while loop
echo "$CONTAINERS_LIST" | while read CONTAINER; do
log_message "Processing container: $CONTAINER"
# Check for the container's OS and run appropriate commands
if $LXC_ATTACH_CMD -n "$CONTAINER" -- test -f /usr/bin/apt >/dev/null 2>&1; then
log_message "Detected APT-based system. Updating..."
$LXC_ATTACH_CMD -n "$CONTAINER" -- bash -c "apt-get update && apt-get upgrade -y && apt-get autoremove -y"
elif $LXC_ATTACH_CMD -n "$CONTAINER" -- test -f /usr/bin/pacman >/dev/null 2>&1; then
log_message "Detected Arch-based system. Updating..."
$LXC_ATTACH_CMD -n "$CONTAINER" -- bash -c "pacman -Syu --noconfirm"
elif $LXC_ATTACH_CMD -n "$CONTAINER" -- test -f /usr/bin/dnf >/dev/null 2>&1; then
log_message "Detected Fedora-based system. Updating..."
$LXC_ATTACH_CMD -n "$CONTAINER" -- bash -c "dnf -y update"
elif $LXC_ATTACH_CMD -n "$CONTAINER" -- test -f /sbin/apk >/dev/null 2>&1; then
log_message "Detected Alpine Linux. Updating..."
$LXC_ATTACH_CMD -n "$CONTAINER" -- sh -c "apk update && apk upgrade && apk-autoremove"
else
log_message "Unknown package manager for $CONTAINER. Skipping."
continue
fi
# Check if a reboot is required
if $LXC_ATTACH_CMD -n "$CONTAINER" -- ls /var/run/reboot-required >/dev/null 2>&1; then
log_message "Reboot required for $CONTAINER. Rebooting now..."
$LXC_STOP_CMD -n "$CONTAINER"
$LXC_START_CMD -n "$CONTAINER"
log_message "$CONTAINER rebooted successfully."
elif $LXC_ATTACH_CMD -n "$CONTAINER" -- /usr/bin/needs-restarting -r >/dev/null 2>&1; then
log_message "Reboot required for $CONTAINER. Rebooting now..."
$LXC_STOP_CMD -n "$CONTAINER"
$LXC_START_CMD -n "$CONTAINER"
log_message "$CONTAINER rebooted successfully."
elif $LXC_ATTACH_CMD -n "$CONTAINER" -- test -f /var/run/reboot-required.pkgs >/dev/null 2>&1; then
log_message "Reboot required for $CONTAINER. Rebooting now..."
$LXC_STOP_CMD -n "$CONTAINER"
$LXC_START_CMD -n "$CONTAINER"
log_message "$CONTAINER rebooted successfully."
else
log_message "No reboot required for $CONTAINER."
fi
done
log_message "---------------------------------------------------"
log_message "LXC container update finished on $(date)"
log_message "---------------------------------------------------"
Then make sure the script can be executed
sudo chmod +x /usr/local/bin/lxc_updater.sh
You can testrun the script with the following command
sudo ./lxc_updater.sh
Finally if you want it to run every month on the first day of the month add a cronjob
sudo crontab -e
And add the following lines to the crontab
# Run the LXC updater script at midnight on the 1:th day of every month
0 0 1 * * /usr/local/bin/lxc_updater.sh