automatic (daily, hourly?) updates of everything internet-reachable is important.

  • of course developers need to provide timely updates for possible cybersec problems
  • users/admins need working update methods that work with minimum downtime

the wordpress “automatic core and plugin auto-updates” feature, has been php-implemented into wordpress for a while and sometimes it even works.

but somteimes it does not (!?).

  • so there might be a reliable mechanism required to:
    • make an backup
    • then reliably run wordperss core and plugin auto update on daily basis

if the user runs it own webserver (vm or dedicated server): https://github.com/wp-cli/wp-cli + the following script 🙂 can do that.

also check out: https://wp-cli.org/

update: 2022

something must have gone wrong.

added “update translations” to the script.

so … updating self hosted wordpress “manual” way, still seems to be ONLY solid option. 🙁

==> /var/log/apache2/domain.com-error.log <== [Tue Dec 13 13:11:18.913569 2022] [php:error] [pid 416927] [client xxx.xxx.xxx.xxx:17253] PHP Fatal error: Uncaught Error: Call to undefined function trailingslashit() in /var/www/html/domain.com/public_html/wp-includes/class-wp-textdomain-registry.php:1 03\nStack trace:\n#0 /var/www/html/domain.com/public_html/wp-includes/l10n.php(784): WP_Textdomain_Registry->set()\n#1 /var/www/html/domain.com/public_html/wp-includes/load.php(1401): load_textdomain()\n#2 /var/www/html/domain.com/public_html/wp-includes/load.php(162): wp_load_translations_early()\n#3 /var/www/html/domain.com/public_html/wp-settings.php(37): wp_check_php_mysql_versions()\n#4 /var/www/html/domain.com/public_html/wp-config.php(93): req
uire_once('...')\n#5 /var/www/html/domain.com/public_html/wp-load.php(50): require_once('...')\n#6 /var/www/html/domain.com/public_html/wp-blog-header.php(13): require_once('...')\n#7 /var/www/html/domain.com/public_ht
ml/index.php(17): require('...')\n#8 {main}\n  thrown in /var/www/html/domain.com/public_html/wp-includes/class-wp-textdomain-registry.php on line 103 

snapshot/backup before update:

because things might break, and then a restore to working state is possible.

GNU Linux Bash – simple backup web root and mysql mariadb database in one go script

install:

the default apache2 user is called www-data and is per default not allowed to login

lsb_release -d; # tested on
Description: Debian GNU/Linux 11 (bullseye)
su - root
mkdir software
cd software
# download the software
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
# check integrity
php wp-cli.phar --info
# install
chmod +x wp-cli.phar
mv - wp-cli.phar /usr/local/bin/wp

# temporarily allow login
usermod -s /bin/bash www-data
# become that user
su - www-data

# cd into a wordpress installation
cd /var/www/html/some-domain.com/

wp --info
# or
wp cli info
OS:	Linux 5.10.0-15-amd64 #1 SMP Debian 5.10.120-1 (2022-06-09) x86_64
Shell:	/bin/sh
PHP binary:	/usr/bin/php8.1
PHP version:	8.1
php.ini used:	/etc/php/8.1/cli/php.ini
MySQL binary:	/usr/bin/mysql
MySQL version:	mysql  Ver 15.1 Distrib 10.5.15-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper
SQL modes:	
WP-CLI root dir:	phar://wp-cli.phar/vendor/wp-cli/wp-cli
WP-CLI vendor dir:	phar://wp-cli.phar/vendor
WP_CLI phar path:	/var/www/html/some-domain.com
WP-CLI packages dir:	
WP-CLI global config:	
WP-CLI project config:	
WP-CLI version:	2.6.0

# what version of wordpress is installed?
wp core version --extra
WordPress version: 6.0.1
Database revision: 53496
TinyMCE version:   4.9110 (49110-20201110)
Package language:  en_US

# update wordperss, if update is available
wp core update
Success: WordPress is up to date.

# list all installed plugins
wp plugin list
+--------------------------+----------+--------+---------+
| name                     | status   | update | version |
+--------------------------+----------+--------+---------+
| antispam-bee             | active   | none   | 2.11.1  |
+--------------------------+----------+--------+---------+


# update plugins
wp plugin update --all

# disable login again for non-root apache2 default user
usermod -s /sbin/nologin www-data

script it:

vim /root/scripts/wordpress_update.sh

#!/bin/bash
# what to backup
WEBROOT=/var/www/html

# temporarily allow non-root apache2 user to login
usermod -s /bin/bash www-data

echo "===== wordpress automatic update single wordpress in web root ===="
INSTALLATION=$WEBROOT
echo "currently installed:";
su www-data -c "wp core version --path=$INSTALLATION";
echo "..... if updates available, updating:"
echo "...core"; su www-data -c "wp core update --path=$INSTALLATION";
echo "...themes"; su www-data -c "wp theme update --all --path=$INSTALLATION";
echo "...plugins"; su www-data -c "wp plugin update --all --path=$INSTALLATION";
# echo "===== wordperss automatic update multiple wordpress in web root ====="
# for FULLPATH in $WEBROOT/*; do
#     if [ -d "$FULLPATH" ]; then
#         BASENAME=$(basename $FULLPATH);
# 
# 	INSTALLATION=$FULLPATH;
# 	# might need modification like this:
# 	# INSTALLATION=$FULLPATH/public_html;
# 
#         echo "=== updating $INSTALLATION ==="
#         echo "currently installed:"; su www-data -c "wp core version --path=$INSTALLATION";
#         echo "..... if updates available, updating:"
#         echo "...core"; su www-data -c "wp core update --path=$INSTALLATION";
#         echo "...themes"; su www-data -c "wp theme update --all --path=$INSTALLATION";
#         echo "...plugins"; su www-data -c "wp plugin update --all --path=$INSTALLATION";
#     fi
# done

# disable login again for non-root apache2 default user
usermod -s /sbin/nologin www-data

echo "=== disable xmlrpc.php because a lot of pwd brute force attacks focus on this file ==="
echo "... also via the readme.html the installed version of wordpress can be identified"
echo "... the following files were found and renamed to .disabled"
find $WEBROOT -type f -name 'xmlrpc.php';
find $WEBROOT -type f -name 'xmlrpc.php' -print0 | xargs --null -I{} mv {} {}.disabled;

find $WEBROOT -type f -name 'liesmich.html';
find $WEBROOT -type f -name 'liesmich.html' -print0 | xargs --null -I{} mv {} {}.disabled;

find $WEBROOT -type f -name 'readme.html';
find $WEBROOT -type f -name 'readme.html' -print0 | xargs --null -I{} mv {} {}.disabled;

find $WEBROOT -type f -name 'license.txt';
find $WEBROOT -type f -name 'license.txt' -print0 | xargs --null -I{} mv {} {}.disabled;

alternative version including update of translations:

#!/bin/bash
# what to backup
WEBROOT=/var/www/html

# temporarily allow non-root apache2 user to login
# /usr/sbin/usermod -s /bin/bash www-data

echo "===== wordperss automatic update all wordpress in web root ====="
for FULLPATH in $WEBROOT/*; do
    if [ -d "$FULLPATH" ]; then
        BASENAME=$(basename $FULLPATH);

	INSTALLATION=$FULLPATH/public_html;

        echo "=== updating $INSTALLATION ==="
        echo "currently installed:"
	wp core version --path=$INSTALLATION
        echo "..... if updates available, updating:"
        echo "...core"
	wp core update --path=$INSTALLATION
        echo "...themes"
	wp theme update --all --path=$INSTALLATION
        echo "...plugins"
	wp plugin update --all --path=$INSTALLATION
	echo "...translations"
	wp language core update --path=$INSTALLATION
    fi
done

cron it:

no need for separate cron job just make it part of the (already existing?) daily update script 🙂

crontab -e
# m h   dom mon dow command
  0 2   *   *   *   /root/scripts/update.sh; # every day 2:00 run updates
cat /root/scripts/update.sh 
#!/bin/bash

echo "=== attempting automatic daily update on $(date '+%Y-%m-%d-%H:%M:%S') ===" | tee -a /scripts/update.sh.log

apt update 2>&1 | tee -a /scripts/update.sh.log
apt -y upgrade 2>&1 | tee -a /scripts/update.sh.log

echo "=== automatically removing un-needed packages (and old kernels) ==="
# keeping too many old kernel versions might fill up boot partition
apt -y autoremove | tee -a /scripts/update.sh.log

echo "=== updating wordpress installations ===" | tee -a /scripts/update.sh.log
/root/scripts/wordpress_update.sh | tee -a /scripts/update.sh.log

echo "=== fine ===" | tee -a /scripts/update.sh.log
echo "" | tee -a /scripts/update.sh.log

manpages:

wp.man.txt

liked this article?

  • only together we can create a truly free world
  • plz support dwaves to keep it up & running!
  • (yes the info on the internet is (mostly) free but beer is still not free (still have to work on that))
  • really really hate advertisement
  • contribute: whenever a solution was found, blog about it for others to find!
  • talk about, recommend & link to this blog and articles
  • thanks to all who contribute!
admin