first commit

This commit is contained in:
Matthew Saunders Brown 2021-04-07 09:43:20 -07:00
commit 4de105a2dd
8 changed files with 535 additions and 0 deletions

19
LICENSE Normal file
View File

@ -0,0 +1,19 @@
MIT License Copyright (c) 2021 Matthew Saunders Brown
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

27
README.md Normal file
View File

@ -0,0 +1,27 @@
# Wordpress Tools
A couple of handy tools for virtualhost servers with wordpress sites.
bash completion for wp-cli
a systemd cron for running wp crons. individual sites don't have to set their own cron job or rely on lazy cron
wp-create-db-user-from-config.sh extracts DB config info from wp-config.php, useful for creating dbs & users for sites that are being migrated
wp-installer.sh automated wp installer
## Install
```
cd /usr/local/src
git clone https://git.stack-source.com/msb/wordpress-tools.git
cd wordpress-tools
cp bash_completion.d/wp-cli /etc/bash_completion.d/
chmod 644 /etc/bash_completion.d/wp-cli
chmod 755 /usr/local/bin/wp-*
cp bin/wp-* /usr/local/bin
cp sbin/wp-cron.sh /usr/local/sbin/
chmod 755 /usr/local/sbin/wp-cron.sh
cp systemd/wp-cron.* /usr/lib/systemd/system/
chmod 644 /usr/lib/systemd/system/wp-cron.*
systemctl daemon-reload
systemctl start wp-cron.timer
```

23
bash_completion.d/wp-cli Normal file
View File

@ -0,0 +1,23 @@
# bash completion for the `wp` command
_wp_complete() {
local OLD_IFS="$IFS"
local cur=${COMP_WORDS[COMP_CWORD]}
IFS=$'\n'; # want to preserve spaces at the end
local opts="$(wp cli completions --line="$COMP_LINE" --point="$COMP_POINT")"
if [[ "$opts" =~ \<file\>\s* ]]
then
COMPREPLY=( $(compgen -f -- $cur) )
elif [[ $opts = "" ]]
then
COMPREPLY=( $(compgen -f -- $cur) )
else
COMPREPLY=( ${opts[*]} )
fi
IFS="$OLD_IFS"
return 0
}
complete -o nospace -F _wp_complete wp

View File

@ -0,0 +1,41 @@
#!/bin/bash
#
# wordpress-tools
# https://git.stack-source.com/msb/wordpress-tools
# MIT License Copyright (c) 2021 Matthew Saunders Brown
# require root
if [ "${EUID}" -ne 0 ]; then
echo "This script must be run as root"
exit
fi
VHOST=$1
if [ ! -f /srv/$VHOST/html/wp-config.php ]; then
echo "Config file /srv/$VHOST/html/wp-config.php does not exist."
exit
fi
# set username
VHOST_USER=$(stat -c '%U' /srv/$VHOST)
cd /srv/$VHOST/html/
DB_NAME=`wp --allow-root config get DB_NAME`
DB_USER=`wp --allow-root config get DB_USER`
DB_PASSWORD=`wp --allow-root config get DB_PASSWORD`
DB_HOST=`wp --allow-root config get DB_HOST`
#if [ $DB_HOST == '127.0.0.1' ]; then
# DB_HOST=localhost
#fi
if [ -d /var/lib/mysql/$DB_NAME ]; then
echo "NOTICE: $DB_NAME already exists"
echo " before proceeding do manual checks for db user"
echo
else
echo mysqladmin create $DB_NAME
fi
echo mysql -e \"CREATE USER \'$DB_USER\'@\'$DB_HOST\' IDENTIFIED BY \'$DB_PASSWORD\'\;\"
echo mysql -e \"GRANT ALL PRIVILEGES ON $DB_NAME.* TO \'$DB_USER\'@\'$DB_HOST\'\;\"

364
bin/wp-installer.sh Executable file
View File

@ -0,0 +1,364 @@
#!/bin/bash
#
# wordpress-tools
# https://git.stack-source.com/msb/wordpress-tools
# MIT License Copyright (c) 2021 Matthew Saunders Brown
# require root
if [ "${EUID}" -ne 0 ]; then
echo "This script must be run as root"
exit
fi
virtualhost_basedir="/srv/www"
virtualhost_htdocsdir="html"
declare -a input_keys_index
input_keys_index=(v r t e u p m d n w x s)
declare -A input_keys_array
input_keys_array[v]="VirtualHost"
input_keys_array[r]="URL"
input_keys_array[t]="Site Title"
input_keys_array[e]="Admin Email"
input_keys_array[u]="Admin Username"
input_keys_array[p]="Admin Password"
input_keys_array[m]="MySQL Hostname"
input_keys_array[d]="MySQL Database"
input_keys_array[n]="MySQL Username"
input_keys_array[w]="MySQL Password"
input_keys_array[x]="MySQL DB Prefix"
input_keys_array[s]="Shell Username"
declare -A input_values_array
help()
{
thisfilename=$(basename -- "$0")
echo "$thisfilename - Install WordPress to a specific VirtualHost."
echo ""
echo "Usage: $thisfilename [-v VirtualHost] [-r URL] [-t Site Title] [-e Admin Email] [-u Admin Username] [-p Admin Password] [-h MySQL Hostname] [-d MySQL Database] [-n MySQL Username] [-w MySQL Password] [-x MySQL DB Prefix] [-s Shell Username]"
echo ""
echo " -v VirtualHost VirtualHost that WordPress install is for, only option that is required - all others have automatic defaults."
echo " -r URL Site URL for WordPress install, defaults to VirtualHost."
echo " -t Site Title Site Title for WordPress install, defaults to VirtualHost."
echo " -e Admin Email Email address for WordPress admin user, defaults to 'Admin username'@'VirtualHost'"
echo " -u Admin Username Username for WordPress admin user, defaults to Shell Username"
echo " -p Admin Password Password for WordPress admin user, random password is generated if not set."
echo " -m MySQL Hostname MySQL Hostname, defaults to 127.0.0.1"
echo " -d MySQL Database MySQL Database, defaults to 'VirtualHost' with dots & dashes changed from symbols to words if not specified."
echo " -n MySQL Username MySQL Username, defaults to 'Shell Username'@'VirtualHost' if not specified."
echo " -w MySQL Password MySQL Hostname, random password is generated if not set."
echo " -x MySQL DB Prefix WordPress db table prefix, defaults to wp_"
echo " -s Shell Username System user that owns website files for this VirtualHost, autodetected and reset if not specified correctly."
echo " -f Force install - skips install confirmation step, for automated installs."
echo " -h Print this help."
echo ""
echo " You will be prompted to any options that were not"
echo " specified on the command line and given a chance"
echo " to confirm before performing the install unless the"
echo " -f option is specified."
exit
}
# force (-f) defaults to false
force=false
# set any options that were passed
while getopts "v:r:t:e:u:p:m:d:n:w:x:s:fh" opt; do
case "${opt}" in
h )
help
exit;;
v )
input_values_array[v]=${OPTARG}
;;
r )
input_values_array[r]=${OPTARG}
;;
t )
input_values_array[t]=${OPTARG}
;;
e )
input_values_array[e]=${OPTARG}
;;
u )
input_values_array[u]=${OPTARG}
;;
p )
input_values_array[p]=${OPTARG}
;;
m )
input_values_array[m]=${OPTARG}
;;
d )
input_values_array[d]=${OPTARG}
;;
n )
input_values_array[n]=${OPTARG}
;;
w )
input_values_array[w]=${OPTARG}
;;
x )
input_values_array[x]=${OPTARG}
;;
s )
input_values_array[s]=${OPTARG}
;;
f )
force=true
;;
\? )
echo "Invalid option: $OPTARG" 1>&2
exit 1;;
: )
echo "Invalid option: $OPTARG requires an argument" 1>&2
exit 1;;
esac
done
# v - virtualhost
function validate_v() {
if [ -d "$virtualhost_basedir/${input_values_array[v]}" ]; then
if [ -d "$virtualhost_basedir/${input_values_array[v]}/$virtualhost_htdocsdir" ]; then
# make sure DocumentRoot is empty (except for possible index.html file)
htdocsdir_file_count=`/usr/bin/ls $virtualhost_basedir/${input_values_array[v]}/$virtualhost_htdocsdir|grep -v index.html|wc -l`
if [ $htdocsdir_file_count -gt 0 ]; then
echo "$virtualhost_basedir/${input_values_array[v]}/$virtualhost_htdocsdir appears to contain an existing website."
echo "Manually remove all files before attempting to install WordPress"
exit
fi
else
echo "${input_values_array[v]} is installed, but DocumentRoot for ${input_values_array[v]} does not exist."
echo "$virtualhost_basedir/${input_values_array[v]}/$virtualhost_htdocsdir"
exit
fi
else
echo "VirtualHost ${input_values_array[v]} is not installed on this server."
echo "$virtualhost_basedir/${input_values_array[v]}/$virtualhost_htdocsdir"
unset input_values_array[v]
fi
}
if [ -n "${input_values_array[v]}" ] ; then
validate_v
fi
if [ -z "${input_values_array[v]}" ] ; then
while [ -z "${input_values_array[v]}" ]; do
read -p "Enter the VirtualHost for WordPress install: " virtualhost
if [ -n "$virtualhost" ] ; then
input_values_array[v]=$virtualhost
validate_v
fi
done
fi
# s - Shell Username
function validate_s() {
# force shell user value, user can't override
shell_username=$(stat -c '%U' $virtualhost_basedir/${input_values_array[v]})
if [[ ${input_values_array[s]} != $shell_username ]]; then
echo "ERROR: Incorrect Shell Username, forcing value reset."
input_values_array[s]=$shell_username
fi
}
if [ -z "${input_values_array[s]}" ] ; then
input_values_array[s]=$(stat -c '%U' $virtualhost_basedir/${input_values_array[v]})
fi
if [ -n "${input_values_array[e]}" ] ; then
validate_s
fi
# u - URL
function validate_u() {
if [[ ${input_values_array[r]} != *"${input_values_array[v]}"* ]] ; then
echo "URL (${input_values_array[r]}) does not appear to be based on VirtualHost (${input_values_array[v]})"
unset input_values_array[r]
fi
}
if [ -z "${input_values_array[r]}" ] ; then
input_values_array[r]="www.${input_values_array[v]}"
fi
if [ -n "${input_values_array[r]}" ] ; then
validate_u
fi
# t - Site Title
if [ -z "${input_values_array[t]}" ] ; then
input_values_array[t]="${input_values_array[v]}"
fi
# e - Admin Email
function validate_e() {
regex="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"
if ! [[ ${input_values_array[e]} =~ $regex ]] ; then
read -p "ERROR: Invalid email address, please re-enter: " admin_email
if [ -n "$admin_email" ] ; then
input_values_array[e]=$admin_email
validate_e
fi
fi
}
if [ -z "${input_values_array[e]}" ] ; then
input_values_array[e]="${input_values_array[s]}@${input_values_array[v]}"
fi
if [ -n "${input_values_array[e]}" ] ; then
validate_e
fi
# u - Admin Username
if [ -z "${input_values_array[u]}" ] ; then
input_values_array[u]=${input_values_array[s]}
fi
# p - Admin Password
if [ -z "${input_values_array[p]}" ] ; then
input_values_array[p]=`pwgen -1 8`
fi
# m - MySQL Hostname
if [ -z "${input_values_array[m]}" ] ; then
input_values_array[m]="127.0.0.1"
fi
# d - MySQL Database
if [ -z "${input_values_array[d]}" ] ; then
mysql_database=${input_values_array[v]}
mysql_database=${mysql_database//./dot}
mysql_database=${mysql_database//-/dash}
input_values_array[d]=$mysql_database
fi
# n - MySQL Username
if [ -z "${input_values_array[n]}" ] ; then
input_values_array[n]="${input_values_array[s]}@${input_values_array[v]}"
fi
# w - MySQL Password
function validate_w() {
mysql_username_count=`mysql -s -N -e "SELECT COUNT(*) FROM mysql.user WHERE User='${input_values_array[n]}'"`
if [[ "$mysql_username_count" -gt 0 ]]; then
mysql_password_verification=`mysql -s -A -N -e "SELECT COUNT(1) Password_is_OK FROM mysql.user WHERE user='${input_values_array[n]}' AND password=PASSWORD('${input_values_array[w]}')"`
if [[ "$mysql_password_verification" -ne 1 ]]; then
read -p "ERROR: Invalid MySQL Password for existing MySQL User ${input_values_array[n]}, please enter current password: " mysql_password
if [ -n "$mysql_password" ] ; then
input_values_array[w]=$mysql_password
restart_script
fi
fi
fi
}
if [ -z "${input_values_array[w]}" ] ; then
input_values_array[w]=`pwgen -1 16`
fi
# x - MySQL DB Prefix
function validate_x() {
if mysql -e "USE ${input_values_array[d]}" 2> /dev/null; then
mysql_db_prefix=`echo ${input_values_array[x]} |sed 's|_|\\\_|g'`
mysql_db_prefix_count=`mysql -s -N -e "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '${input_values_array[d]}' AND TABLE_NAME LIKE '$mysql_db_prefix%'"`
if [[ "$mysql_db_prefix_count" -gt 0 ]]; then
read -p "One or more MySQL tables with DB Prefix '${input_values_array[x]}' already exist, please enter new prefix: " mysql_db_prefix
if [ -n "$mysql_db_prefix" ] ; then
input_values_array[x]=$mysql_db_prefix
restart_script
fi
fi
fi
}
if [ -z "${input_values_array[x]}" ] ; then
input_values_array[x]="wp_"
fi
# if [ -n "${input_values_array[x]}" ] ; then
# validate_x
# fi
# display confirmation
function display_confirmation() {
echo
for key in "${!input_keys_index[@]}" ; do
value=${input_keys_index[$key]}
echo "$value - ${input_keys_array[$value]}: ${input_values_array[$value]}"
done
echo
echo "i - install now with these settings"
echo "q - quit without installing"
echo
read -p "Select option to edit or install/quit: " option
echo
}
function restart_script() {
# set command line args
cli_args=
for key in "${!input_values_array[@]}" ; do
value=${input_values_array[$key]}
cli_args="$cli_args -$key '$value'"
done
# echo "${0} $cli_args"
echo
eval ${0} $cli_args
exit
}
if [[ "$force" == "false" ]]; then
display_confirmation
else
option="i"
fi
if [[ "$option" == "i" ]]; then
# validate MySQL DB Prefix
validate_x
# validate MySQL User Password
validate_w
echo
echo "Installing WP for VirtualHost ${input_values_array[v]} now..."
# create database if it doesn't already exist
if ! mysql -e "USE ${input_values_array[d]}" 2> /dev/null; then
mysqladmin create ${input_values_array[d]}
fi
# create mysql user if they don't already exist
if [[ "$mysql_username_count" -eq 0 ]]; then
mysql -e "CREATE USER '${input_values_array[n]}'@'${input_values_array[m]}' IDENTIFIED BY '${input_values_array[w]}'"
fi
# add db privileges for mysql user if no already enabled
if ! mysql --host=${input_values_array[m]} --user=${input_values_array[n]} --password=${input_values_array[w]} -e "USE ${input_values_array[d]}" 2> /dev/null; then
mysql -e "GRANT ALL PRIVILEGES ON ${input_values_array[d]}.* TO '${input_values_array[n]}'@'${input_values_array[m]}'"
mysqladmin flush-privileges
fi
# switch to Shell User and install WordPress
sudo -u ${input_values_array[s]} --shell /bin/bash << EOF
cd $virtualhost_basedir/${input_values_array[v]}/$virtualhost_htdocsdir
wp core download
wp config create --dbhost="${input_values_array[m]}" --dbname=${input_values_array[d]} --dbuser="${input_values_array[n]}" --dbpass="${input_values_array[w]}" --dbprefix="${input_values_array[x]}"
wp config set DISALLOW_FILE_EDIT true
wp config set DISABLE_WP_CRON true
wp core install --url="${input_values_array[u]}" --title="${input_values_array[v]}" --admin_user=${input_values_array[u]} --admin_password="${input_values_array[p]}" --admin_email=${input_values_array[e]}
echo "apache_modules:" > wp-cli.local.yml
echo " - mod_rewrite" >> wp-cli.local.yml
wp rewrite flush --hard
rm wp-cli.local.yml
EOF
if [ -f "$virtualhost_basedir/${input_values_array[v]}/$virtualhost_htdocsdir/index.html" ]; then
/usr/bin/rm $virtualhost_basedir/${input_values_array[v]}/$virtualhost_htdocsdir/index.html
fi
elif [[ "$option" == "q" ]]; then
echo "Quiting without installing."
elif [[ " ${input_keys_index[@]} " =~ " $option " ]]; then
read -p "Enter new value for ${input_keys_array[$option]} (${input_values_array[$option]}): " new_value
if [ -n "$new_value" ] ; then
input_values_array[$option]=$new_value
fi
restart_script
else
echo "ERROR: Invalid entry, try again."
fi

35
sbin/wp-cron.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/bash
#
# wordpress-tools
# https://git.stack-source.com/msb/wordpress-tools
# MIT License Copyright (c) 2021 Matthew Saunders Brown
# must be root, will su to vhost users for wp cron runs
if [ "$USER" != "root" ]; then
exec sudo $0
fi
declare -a virtualhostExclusionArray
# optionally add virtualhosts to virtualhostExclusionArray to have them skipped
# create virtualhostArray
cd /srv/www
virtualhostArray=(`ls -1|grep -v ^html$`)
for VHOST in "${virtualhostArray[@]}"
do
# check if VHOST has been added to exclustion array
if [[ ! " ${virtualhostExclusionArray[@]} " =~ " ${VHOST} " ]]; then
# basic check for WP install
if [ -f /srv/www/$VHOST/html/wp-config.php ]; then
VHOST_USER=$(stat -c '%U' /srv/www/$VHOST)
# confirm that WP really is installed
if $(su -c "wp core is-installed --path=/srv/www/$VHOST/html/" $VHOST_USER); then
# run cron for VHOST as VHOST_USER
/usr/bin/logger --tag wp-cron "running wp-cli cron for $VHOST as $VHOST_USER"
su -c "/usr/local/bin/wp cron event run --due-now --quiet --path=/srv/www/$VHOST/html/" $VHOST_USER
fi
fi
fi
done

13
systemd/wp-cron.service Normal file
View File

@ -0,0 +1,13 @@
# wordpress-tools
# https://git.stack-source.com/msb/wordpress-tools
# MIT License Copyright (c) 2021 Matthew Saunders Brown
#
[Unit]
Description=WP CLI cron
[Service]
Type=simple
ExecStart=/usr/local/sbin/wp-cron.sh
[Install]
WantedBy=multi-user.target

13
systemd/wp-cron.timer Normal file
View File

@ -0,0 +1,13 @@
# wordpress-tools
# https://git.stack-source.com/msb/wordpress-tools
# MIT License Copyright (c) 2021 Matthew Saunders Brown
#
[Unit]
Description=WP CLI cron for all virtualhosts every 15 minutes
[Timer]
OnCalendar=*:0/15
Unit=wp-cron.service
[Install]
WantedBy=multi-user.target