<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>WP-CLI Mastery</title>
	<atom:link href="https://wpclimastery.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://wpclimastery.com/</link>
	<description>Automate WordPress Like a DevOps Pro.</description>
	<lastBuildDate>Mon, 24 Nov 2025 11:16:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://wpclimastery.com/wp-content/uploads/2025/11/cropped-favicon-32x32.webp</url>
	<title>WP-CLI Mastery</title>
	<link>https://wpclimastery.com/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WordPress Multisite Network Management with WP-CLI: Complete Guide</title>
		<link>https://wpclimastery.com/blog/wordpress-multisite-network-management-with-wp-cli-complete-guide/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Wed, 25 Feb 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Multisite Management]]></category>
		<category><![CDATA[multisite automation]]></category>
		<category><![CDATA[network management wordpress]]></category>
		<category><![CDATA[wordpress multisite]]></category>
		<category><![CDATA[wordpress network commands]]></category>
		<category><![CDATA[wp-cli multisite]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=161</guid>

					<description><![CDATA[<p>Managing dozens or hundreds of WordPress Multisite network sites through the admin dashboard is tedious—creating sites manually, adding users one-by-one, updating plugins across all sites, and managing network settings requires...</p>
<p>The post <a href="https://wpclimastery.com/blog/wordpress-multisite-network-management-with-wp-cli-complete-guide/">WordPress Multisite Network Management with WP-CLI: Complete Guide</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Managing dozens or hundreds of WordPress Multisite network sites through the admin dashboard is tedious—creating sites manually, adding users one-by-one, updating plugins across all sites, and managing network settings requires hours of repetitive clicking.</p>



<p>WP-CLI transforms WordPress Multisite management with powerful network commands that create sites instantly, bulk manage users, update plugins network-wide, and automate complex operations across hundreds of sites with single commands.</p>



<p>In this guide, you’ll master WordPress Multisite network management with WP-CLI, from basic site creation to advanced bulk operations managing large-scale WordPress networks efficiently.</p>



<h3 class="wp-block-heading" id="why-multisite-wpcli">Why Use WP-CLI for Multisite?</h3>



<p><a href="https://wordpress.org/support/article/create-a-network/">WordPress Multisite dashboard management</a> doesn’t scale when managing more than a handful of sites.</p>



<h4 class="wp-block-heading" id="dashboard-management-limitations">Dashboard Management Limitations</h4>



<p><strong>Time-consuming</strong>: Creating sites manually takes 5-10 minutes each.</p>



<p><strong>No bulk operations</strong>: Must update plugins/themes on each site individually.</p>



<p><strong>Limited automation</strong>: Can’t script repetitive network operations.</p>



<p><strong>User management complexity</strong>: Adding users across multiple sites is tedious.</p>



<p><strong>No reporting</strong>: Can’t generate network-wide statistics easily.</p>



<h4 class="wp-block-heading" id="wp-cli-multisite-advantages">WP-CLI Multisite Advantages</h4>



<p><strong>Instant site creation</strong>: Create dozens of sites in seconds with scripts.</p>



<p><strong>Network-wide updates</strong>: Update plugins/themes across all sites with one command.</p>



<p><strong>Bulk user management</strong>: Add/remove users from multiple sites simultaneously.</p>



<p><strong>Complete automation</strong>: Script complex network operations and scheduling.</p>



<p><strong>Powerful reporting</strong>: Generate comprehensive network statistics instantly.</p>



<p>According to <a href="https://codex.wordpress.org/Multisite_Network_Administration">WordPress Multisite best practices</a>, WP-CLI reduces network management time by 80% for networks with 10+ sites.</p>



<h3 class="wp-block-heading" id="network-commands">Multisite Network Commands Overview</h3>



<p>Essential WP-CLI commands for Multisite networks.</p>



<h4 class="wp-block-heading" id="basic-network-information">Basic Network Information</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="co"># Check if Multisite is enabled</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="ex">wp</span> core is-installed --network</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a><span class="co"># List all sites in network</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a><span class="ex">wp</span> site list</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a><span class="co"># Get network details</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a><span class="ex">wp</span> site list --format=table --fields=blog_id,url,registered</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a><span class="co"># Count total sites</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a><span class="ex">wp</span> site list --format=count</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a><span class="co"># List sites with specific criteria</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a><span class="ex">wp</span> site list --field=url --archived=0 --deleted=0</span></code></pre>
</div>



<h4 class="wp-block-heading" id="network-site-management">Network Site Management</h4>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="co"># Create new site</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a><span class="ex">wp</span> site create --slug=newsite --title=<span class="st">"New Site"</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a><span class="co"># Create site with custom email</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a><span class="ex">wp</span> site create <span class="kw">\</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a>    <span class="ex">--slug</span>=department <span class="kw">\</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a>    <span class="ex">--title</span>=<span class="st">"Department Site"</span> <span class="kw">\</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a>    <span class="ex">--email</span>=admin@department.com</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a><span class="co"># Delete site</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a><span class="ex">wp</span> site delete 5 --yes</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a><span class="co"># Archive site</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true"></a><span class="ex">wp</span> site archive 5</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true"></a><span class="co"># Unarchive site</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true"></a><span class="ex">wp</span> site unarchive 5</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true"></a><span class="co"># Mark site as spam</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true"></a><span class="ex">wp</span> site spam 5</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true"></a></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true"></a><span class="co"># Empty (delete all content but keep site)</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true"></a><span class="ex">wp</span> site empty 5 --yes</span></code></pre>
</div>



<p>Learn about <a href="https://developer.wordpress.org/advanced-administration/multisite/create-network/">WordPress Multisite architecture</a>.</p>



<h3 class="wp-block-heading" id="bulk-site-creation">Bulk Site Creation and Provisioning</h3>



<p>Automate creating multiple sites programmatically.</p>



<h4 class="wp-block-heading" id="batch-site-creation-script">Batch Site Creation Script</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># create-sites-batch.sh - Create multiple sites from CSV</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="va">SITES_CSV=</span><span class="st">"sites.csv"</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$SITES_CSV</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"ERROR: </span><span class="va">$SITES_CSV</span><span class="st"> not found"</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Creating sites from </span><span class="va">$SITES_CSV</span><span class="st">"</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a><span class="co"># Skip header row, read CSV</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a><span class="fu">tail</span> -n +2 <span class="st">"</span><span class="va">$SITES_CSV</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">while</span> <span class="va">IFS=</span>, <span class="bu">read</span> -r <span class="va">SLUG</span> <span class="va">TITLE</span> <span class="va">EMAIL</span>; <span class="kw">do</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Creating site: </span><span class="va">$SLUG</span><span class="st">"</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a>    <span class="co"># Check if site already exists</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> site list --field=url <span class="kw">|</span> <span class="fu">grep</span> -q <span class="st">"/</span><span class="va">$SLUG</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"⊘ Site </span><span class="va">$SLUG</span><span class="st"> already exists, skipping"</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a>        <span class="bu">continue</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a>    <span class="co"># Create site</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a>    <span class="va">SITE_ID=$(</span><span class="ex">wp</span> site create <span class="kw">\</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a>        <span class="ex">--slug</span>=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true"></a>        <span class="ex">--title</span>=<span class="st">"</span><span class="va">$TITLE</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true"></a>        <span class="ex">--email</span>=<span class="st">"</span><span class="va">$EMAIL</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a>        <span class="ex">--porcelain</span><span class="va">)</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="va">$?</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ Created site: </span><span class="va">$SLUG</span><span class="st"> (ID: </span><span class="va">$SITE_ID</span><span class="st">)"</span></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✗ Failed to create site: </span><span class="va">$SLUG</span><span class="st">"</span></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true"></a></span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Batch site creation complete"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="sites-csv-template">Sites CSV Template</h4>



<pre class="wp-block-code"><code>slug,title,email
sales,Sales Department,sales@example.com
marketing,Marketing Department,marketing@example.com
support,Support Department,support@example.com
engineering,Engineering Department,engineering@example.com</code></pre>



<h4 class="wp-block-heading" id="automated-site-provisioning">Automated Site Provisioning</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="co"># provision-new-site.sh - Complete site setup</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">SLUG=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="va">TITLE=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a><span class="va">ADMIN_EMAIL=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span><span class="bu"> ]</span> <span class="kw">||</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$TITLE</span><span class="st">"</span><span class="bu"> ]</span> <span class="kw">||</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$ADMIN_EMAIL</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;slug&gt; &lt;title&gt; &lt;admin_email&gt;"</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Provisioning new site: </span><span class="va">$SLUG</span><span class="st">"</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a><span class="co"># Create site</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a><span class="va">SITE_ID=$(</span><span class="ex">wp</span> site create <span class="kw">\</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a>    <span class="ex">--slug</span>=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a>    <span class="ex">--title</span>=<span class="st">"</span><span class="va">$TITLE</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a>    <span class="ex">--email</span>=<span class="st">"</span><span class="va">$ADMIN_EMAIL</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true"></a>    <span class="ex">--porcelain</span><span class="va">)</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true"></a></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Site created (ID: </span><span class="va">$SITE_ID</span><span class="st">)"</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true"></a></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true"></a><span class="co"># Switch to new site context</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true"></a><span class="bu">export</span> <span class="va">WP_CLI_STRICT_ARGS_MODE=</span>1</span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true"></a></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true"></a><span class="co"># Install and activate plugins</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Installing plugins..."</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true"></a><span class="ex">wp</span> plugin install --activate <span class="kw">\</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true"></a>    <span class="ex">--url</span>=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true"></a>    <span class="ex">wordpress-seo</span> <span class="kw">\</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true"></a>    <span class="ex">contact-form-7</span> <span class="kw">\</span></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true"></a>    <span class="ex">wordfence</span></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true"></a></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true"></a><span class="co"># Install theme</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Installing theme..."</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true"></a><span class="ex">wp</span> theme install twentytwentyfour --activate --url=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span></span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true"></a></span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true"></a><span class="co"># Create default pages</span></span>
<span id="cb5-40"><a href="#cb5-40" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Creating default pages..."</span></span>
<span id="cb5-41"><a href="#cb5-41" aria-hidden="true"></a><span class="ex">wp</span> post create <span class="kw">\</span></span>
<span id="cb5-42"><a href="#cb5-42" aria-hidden="true"></a>    <span class="ex">--url</span>=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-43"><a href="#cb5-43" aria-hidden="true"></a>    <span class="ex">--post_type</span>=page <span class="kw">\</span></span>
<span id="cb5-44"><a href="#cb5-44" aria-hidden="true"></a>    <span class="ex">--post_title</span>=<span class="st">'Home'</span> <span class="kw">\</span></span>
<span id="cb5-45"><a href="#cb5-45" aria-hidden="true"></a>    <span class="ex">--post_status</span>=publish <span class="kw">\</span></span>
<span id="cb5-46"><a href="#cb5-46" aria-hidden="true"></a>    <span class="ex">--post_content</span>=<span class="st">'Welcome to our site'</span></span>
<span id="cb5-47"><a href="#cb5-47" aria-hidden="true"></a></span>
<span id="cb5-48"><a href="#cb5-48" aria-hidden="true"></a><span class="ex">wp</span> post create <span class="kw">\</span></span>
<span id="cb5-49"><a href="#cb5-49" aria-hidden="true"></a>    <span class="ex">--url</span>=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-50"><a href="#cb5-50" aria-hidden="true"></a>    <span class="ex">--post_type</span>=page <span class="kw">\</span></span>
<span id="cb5-51"><a href="#cb5-51" aria-hidden="true"></a>    <span class="ex">--post_title</span>=<span class="st">'About'</span> <span class="kw">\</span></span>
<span id="cb5-52"><a href="#cb5-52" aria-hidden="true"></a>    <span class="ex">--post_status</span>=publish</span>
<span id="cb5-53"><a href="#cb5-53" aria-hidden="true"></a></span>
<span id="cb5-54"><a href="#cb5-54" aria-hidden="true"></a><span class="ex">wp</span> post create <span class="kw">\</span></span>
<span id="cb5-55"><a href="#cb5-55" aria-hidden="true"></a>    <span class="ex">--url</span>=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-56"><a href="#cb5-56" aria-hidden="true"></a>    <span class="ex">--post_type</span>=page <span class="kw">\</span></span>
<span id="cb5-57"><a href="#cb5-57" aria-hidden="true"></a>    <span class="ex">--post_title</span>=<span class="st">'Contact'</span> <span class="kw">\</span></span>
<span id="cb5-58"><a href="#cb5-58" aria-hidden="true"></a>    <span class="ex">--post_status</span>=publish</span>
<span id="cb5-59"><a href="#cb5-59" aria-hidden="true"></a></span>
<span id="cb5-60"><a href="#cb5-60" aria-hidden="true"></a><span class="co"># Set front page</span></span>
<span id="cb5-61"><a href="#cb5-61" aria-hidden="true"></a><span class="va">HOME_ID=$(</span><span class="ex">wp</span> post list --url=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> --post_type=page --name=home --field=ID<span class="va">)</span></span>
<span id="cb5-62"><a href="#cb5-62" aria-hidden="true"></a><span class="ex">wp</span> option update --url=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> page_on_front <span class="st">"</span><span class="va">$HOME_ID</span><span class="st">"</span></span>
<span id="cb5-63"><a href="#cb5-63" aria-hidden="true"></a><span class="ex">wp</span> option update --url=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> show_on_front page</span>
<span id="cb5-64"><a href="#cb5-64" aria-hidden="true"></a></span>
<span id="cb5-65"><a href="#cb5-65" aria-hidden="true"></a><span class="co"># Configure settings</span></span>
<span id="cb5-66"><a href="#cb5-66" aria-hidden="true"></a><span class="ex">wp</span> option update --url=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> blogdescription <span class="st">"Powered by WordPress Multisite"</span></span>
<span id="cb5-67"><a href="#cb5-67" aria-hidden="true"></a><span class="ex">wp</span> option update --url=<span class="st">"</span><span class="va">$SLUG</span><span class="st">"</span> permalink_structure <span class="st">'/%postname%/'</span></span>
<span id="cb5-68"><a href="#cb5-68" aria-hidden="true"></a></span>
<span id="cb5-69"><a href="#cb5-69" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Site provisioning complete: </span><span class="va">$SLUG</span><span class="st">"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="network-plugins">Network-Wide Plugin and Theme Management</h3>



<p>Manage plugins and themes across all sites.</p>



<h4 class="wp-block-heading" id="network-wide-plugin-operations">Network-Wide Plugin Operations</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co"># Install plugin network-wide</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="ex">wp</span> plugin install akismet --network</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="co"># Activate plugin for entire network</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="ex">wp</span> plugin activate akismet --network</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="co"># Deactivate network-wide</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a><span class="ex">wp</span> plugin deactivate akismet --network</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a><span class="co"># Update all plugins across all sites</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Updating plugins for: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a>    <span class="ex">wp</span> plugin update --all --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true"></a><span class="co"># Check plugin status across network</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true"></a><span class="ex">wp</span> site list --field=url <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">site_url</span>; <span class="kw">do</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"=== Plugins on </span><span class="va">$site_url</span><span class="st"> ==="</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true"></a>    <span class="ex">wp</span> plugin list --url=<span class="st">"</span><span class="va">$site_url</span><span class="st">"</span> --status=active --format=table</span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="bulk-theme-management">Bulk Theme Management</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="co"># manage-themes-network.sh</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a><span class="va">ACTION=</span><span class="st">"</span><span class="va">${1:-</span>list<span class="va">}</span><span class="st">"</span>  # <span class="ex">list</span>, install, activate, delete</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a><span class="kw">case</span> <span class="st">"</span><span class="va">$ACTION</span><span class="st">"</span><span class="kw"> in</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a>    list<span class="kw">)</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Themes across network:"</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a>        <span class="ex">wp</span> site list --field=url <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">url</span>; <span class="kw">do</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"Site: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a>            <span class="ex">wp</span> theme list --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span> --status=active --fields=name,version</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a>        <span class="kw">done</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a>    install<span class="kw">)</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a>        <span class="va">THEME=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Installing </span><span class="va">$THEME</span><span class="st"> on all sites..."</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a>        <span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a>            <span class="ex">wp</span> theme install <span class="st">"</span><span class="va">$THEME</span><span class="st">"</span> --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a>        <span class="kw">done</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a>    activate<span class="kw">)</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true"></a>        <span class="va">THEME=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Activating </span><span class="va">$THEME</span><span class="st"> on all sites..."</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true"></a>        <span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true"></a>            <span class="ex">wp</span> theme activate <span class="st">"</span><span class="va">$THEME</span><span class="st">"</span> --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true"></a>        <span class="kw">done</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true"></a></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true"></a>    delete<span class="kw">)</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true"></a>        <span class="va">THEME=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Deleting </span><span class="va">$THEME</span><span class="st"> from all sites..."</span></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true"></a>        <span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true"></a>            <span class="ex">wp</span> theme delete <span class="st">"</span><span class="va">$THEME</span><span class="st">"</span> --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true"></a>        <span class="kw">done</span></span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true"></a></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true"></a>    *<span class="kw">)</span></span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> {list|install|activate|delete} [theme-name]"</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true"></a>        <span class="bu">exit</span> 1</span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true"></a><span class="kw">esac</span></span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/support/article/multisite-network-administration/#plugins">Multisite plugin management</a>.</p>



<h3 class="wp-block-heading" id="user-management">User Management Across Network</h3>



<p>Manage users and roles across multiple sites.</p>



<h4 class="wp-block-heading" id="add-users-to-multiple-sites">Add Users to Multiple Sites</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="co"># add-user-to-sites.sh - Add user to multiple sites</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a><span class="va">USERNAME=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a><span class="va">ROLE=</span><span class="st">"</span><span class="va">${2:-</span>subscriber<span class="va">}</span><span class="st">"</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$USERNAME</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;username&gt; [role]"</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true"></a><span class="co"># Check if user exists</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> user get <span class="st">"</span><span class="va">$USERNAME</span><span class="st">"</span> <span class="op">&amp;&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"ERROR: User </span><span class="va">$USERNAME</span><span class="st"> does not exist"</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true"></a></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Adding </span><span class="va">$USERNAME</span><span class="st"> as </span><span class="va">$ROLE</span><span class="st"> to all sites..."</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a><span class="co"># Get all site IDs</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a><span class="va">SITES=$(</span><span class="ex">wp</span> site list --field=blog_id<span class="va">)</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">SITE_ID</span> in <span class="va">$SITES</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a>    <span class="va">SITE_URL=$(</span><span class="ex">wp</span> site list --blog_id=<span class="st">"</span><span class="va">$SITE_ID</span><span class="st">"</span> --field=url<span class="va">)</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true"></a>    <span class="co"># Add user to site</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true"></a>    <span class="ex">wp</span> user set-role <span class="st">"</span><span class="va">$USERNAME</span><span class="st">"</span> <span class="st">"</span><span class="va">$ROLE</span><span class="st">"</span> --url=<span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true"></a></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="va">$?</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ Added to: </span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✗ Failed: </span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true"></a></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"User addition complete"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="bulk-user-role-management">Bulk User Role Management</h4>



<div class="sourceCode" id="cb9">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a><span class="co"># manage-user-roles.sh</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a><span class="co"># List all users across network</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a><span class="fu">network_user_report()</span> <span class="kw">{</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Network User Report"</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"==================="</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a>    <span class="ex">wp</span> site list --field=url <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">url</span>; <span class="kw">do</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Site: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a>        <span class="ex">wp</span> user list --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span> --format=table --fields=user_login,roles,user_email</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true"></a><span class="co"># Remove user from all sites</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true"></a><span class="fu">remove_user_network()</span> <span class="kw">{</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">username=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true"></a></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Removing </span><span class="va">$username</span><span class="st"> from all sites..."</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true"></a></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true"></a>    <span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true"></a>        <span class="kw">if</span> <span class="ex">wp</span> user list --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span> --field=user_login <span class="kw">|</span> <span class="fu">grep</span> -q <span class="st">"^</span><span class="va">$username</span><span class="st"><pre wp-pre-tag-8=""></pre>quot;</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true"></a>            <span class="ex">wp</span> user remove-role <span class="st">"</span><span class="va">$username</span><span class="st">"</span> --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"✓ Removed from: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true"></a></span>
<span id="cb9-30"><a href="#cb9-30" aria-hidden="true"></a><span class="co"># Promote user to admin on all sites</span></span>
<span id="cb9-31"><a href="#cb9-31" aria-hidden="true"></a><span class="fu">promote_to_admin_network()</span> <span class="kw">{</span></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">username=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb9-33"><a href="#cb9-33" aria-hidden="true"></a></span>
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Promoting </span><span class="va">$username</span><span class="st"> to administrator on all sites..."</span></span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true"></a></span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true"></a>    <span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true"></a>        <span class="ex">wp</span> user set-role <span class="st">"</span><span class="va">$username</span><span class="st">"</span> administrator --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ Promoted on: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb9-39"><a href="#cb9-39" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb9-40"><a href="#cb9-40" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb9-41"><a href="#cb9-41" aria-hidden="true"></a></span>
<span id="cb9-42"><a href="#cb9-42" aria-hidden="true"></a><span class="co"># Main script</span></span>
<span id="cb9-43"><a href="#cb9-43" aria-hidden="true"></a><span class="kw">case</span> <span class="st">"</span><span class="va">$1</span><span class="st">"</span><span class="kw"> in</span></span>
<span id="cb9-44"><a href="#cb9-44" aria-hidden="true"></a>    report<span class="kw">)</span></span>
<span id="cb9-45"><a href="#cb9-45" aria-hidden="true"></a>        <span class="ex">network_user_report</span></span>
<span id="cb9-46"><a href="#cb9-46" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb9-47"><a href="#cb9-47" aria-hidden="true"></a>    remove<span class="kw">)</span></span>
<span id="cb9-48"><a href="#cb9-48" aria-hidden="true"></a>        <span class="ex">remove_user_network</span> <span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb9-49"><a href="#cb9-49" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb9-50"><a href="#cb9-50" aria-hidden="true"></a>    promote<span class="kw">)</span></span>
<span id="cb9-51"><a href="#cb9-51" aria-hidden="true"></a>        <span class="ex">promote_to_admin_network</span> <span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb9-52"><a href="#cb9-52" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb9-53"><a href="#cb9-53" aria-hidden="true"></a>    *<span class="kw">)</span></span>
<span id="cb9-54"><a href="#cb9-54" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> {report|remove|promote} [username]"</span></span>
<span id="cb9-55"><a href="#cb9-55" aria-hidden="true"></a>        <span class="bu">exit</span> 1</span>
<span id="cb9-56"><a href="#cb9-56" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb9-57"><a href="#cb9-57" aria-hidden="true"></a><span class="kw">esac</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="super-admin-management">Super Admin Management</h4>



<div class="sourceCode" id="cb10">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a><span class="co"># Grant super admin privileges</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a><span class="ex">wp</span> super-admin add username</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a><span class="co"># Remove super admin privileges</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a><span class="ex">wp</span> super-admin remove username</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a><span class="co"># List all super admins</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a><span class="ex">wp</span> super-admin list</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a><span class="co"># Check if user is super admin</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a><span class="ex">wp</span> user get username --field=caps <span class="kw">|</span> <span class="fu">grep</span> -q <span class="st">"super_admin"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="network-reporting">Network Statistics and Reporting</h3>



<p>Generate comprehensive network reports.</p>



<h4 class="wp-block-heading" id="network-health-report">Network Health Report</h4>



<div class="sourceCode" id="cb11">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="co"># network-health-report.sh</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a><span class="va">REPORT_FILE=</span><span class="st">"/tmp/multisite-health-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d<span class="va">)</span><span class="st">.txt"</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a><span class="kw">{</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"WordPress Multisite Network Health Report"</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"=========================================="</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Generated: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true"></a></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true"></a>    <span class="co"># Network overview</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Network Overview"</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"----------------"</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true"></a>    <span class="va">SITE_COUNT=$(</span><span class="ex">wp</span> site list --format=count<span class="va">)</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true"></a>    <span class="va">ACTIVE_SITES=$(</span><span class="ex">wp</span> site list --archived=0 --deleted=0 --format=count<span class="va">)</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true"></a>    <span class="va">ARCHIVED_SITES=$(</span><span class="ex">wp</span> site list --archived=1 --format=count<span class="va">)</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true"></a>    <span class="va">DELETED_SITES=$(</span><span class="ex">wp</span> site list --deleted=1 --format=count<span class="va">)</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true"></a></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Total sites: </span><span class="va">$SITE_COUNT</span><span class="st">"</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Active sites: </span><span class="va">$ACTIVE_SITES</span><span class="st">"</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Archived sites: </span><span class="va">$ARCHIVED_SITES</span><span class="st">"</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Deleted sites: </span><span class="va">$DELETED_SITES</span><span class="st">"</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true"></a></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true"></a>    <span class="co"># User statistics</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"User Statistics"</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"---------------"</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true"></a>    <span class="va">TOTAL_USERS=$(</span><span class="ex">wp</span> user list --format=count<span class="va">)</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true"></a>    <span class="va">SUPER_ADMINS=$(</span><span class="ex">wp</span> super-admin list --format=count<span class="va">)</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true"></a></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Total users: </span><span class="va">$TOTAL_USERS</span><span class="st">"</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Super admins: </span><span class="va">$SUPER_ADMINS</span><span class="st">"</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true"></a></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true"></a>    <span class="co"># Plugin status across network</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Network Plugin Status"</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"---------------------"</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Network-activated plugins:"</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true"></a>    <span class="ex">wp</span> plugin list --status=active-network --format=table --fields=name,version</span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true"></a></span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true"></a>    <span class="co"># Site details</span></span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Site Details"</span></span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"------------"</span></span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true"></a>    <span class="ex">wp</span> site list --format=table --fields=blog_id,url,registered,last_updated</span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true"></a></span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-49"><a href="#cb11-49" aria-hidden="true"></a></span>
<span id="cb11-50"><a href="#cb11-50" aria-hidden="true"></a>    <span class="co"># Storage usage (if multisite uses subdirectories)</span></span>
<span id="cb11-51"><a href="#cb11-51" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Storage Usage"</span></span>
<span id="cb11-52"><a href="#cb11-52" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"-------------"</span></span>
<span id="cb11-53"><a href="#cb11-53" aria-hidden="true"></a>    <span class="kw">for</span> <span class="ex">site_id</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=blog_id<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb11-54"><a href="#cb11-54" aria-hidden="true"></a>        <span class="va">url=$(</span><span class="ex">wp</span> site list --blog_id=<span class="st">"</span><span class="va">$site_id</span><span class="st">"</span> --field=url<span class="va">)</span></span>
<span id="cb11-55"><a href="#cb11-55" aria-hidden="true"></a>        <span class="va">uploads_dir=</span><span class="st">"wp-content/uploads/sites/</span><span class="va">$site_id</span><span class="st">"</span></span>
<span id="cb11-56"><a href="#cb11-56" aria-hidden="true"></a></span>
<span id="cb11-57"><a href="#cb11-57" aria-hidden="true"></a>        <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-d</span> <span class="st">"</span><span class="va">$uploads_dir</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-58"><a href="#cb11-58" aria-hidden="true"></a>            <span class="va">size=$(</span><span class="fu">du</span> -sh <span class="st">"</span><span class="va">$uploads_dir</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">cut</span> -f1<span class="va">)</span></span>
<span id="cb11-59"><a href="#cb11-59" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"</span><span class="va">$url</span><span class="st">: </span><span class="va">$size</span><span class="st">"</span></span>
<span id="cb11-60"><a href="#cb11-60" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb11-61"><a href="#cb11-61" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb11-62"><a href="#cb11-62" aria-hidden="true"></a></span>
<span id="cb11-63"><a href="#cb11-63" aria-hidden="true"></a><span class="kw">}</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb11-64"><a href="#cb11-64" aria-hidden="true"></a></span>
<span id="cb11-65"><a href="#cb11-65" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Report generated: </span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb11-66"><a href="#cb11-66" aria-hidden="true"></a></span>
<span id="cb11-67"><a href="#cb11-67" aria-hidden="true"></a><span class="co"># Email report</span></span>
<span id="cb11-68"><a href="#cb11-68" aria-hidden="true"></a><span class="ex">mail</span> -s <span class="st">"Multisite Network Health Report"</span> admin@example.com <span class="op">&lt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="activity-monitoring">Activity Monitoring</h4>



<div class="sourceCode" id="cb12">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a><span class="co"># monitor-network-activity.sh</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Network Activity Monitor"</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"========================"</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true"></a></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a><span class="co"># Recently created sites</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Recently Created Sites (last 7 days):"</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true"></a><span class="ex">wp</span> site list --format=table --fields=blog_id,url,registered <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true"></a>    <span class="fu">grep</span> <span class="st">"</span><span class="va">$(</span><span class="fu">date</span> -d <span class="st">'7 days ago'</span> <span class="st">'+%Y-%m-%d'</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true"></a></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true"></a></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true"></a><span class="co"># Recently updated sites</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Recently Updated Sites:"</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true"></a><span class="ex">wp</span> site list --format=table --fields=blog_id,url,last_updated</span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true"></a></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true"></a></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true"></a><span class="co"># New users (last 24 hours)</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"New Users (last 24 hours):"</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true"></a><span class="ex">wp</span> user list --format=table --fields=user_login,user_email,user_registered <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true"></a>    <span class="fu">grep</span> <span class="st">"</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d'</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true"></a></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true"></a></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true"></a><span class="co"># Plugin update status</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Sites Needing Plugin Updates:"</span></span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true"></a>    <span class="va">UPDATES=$(</span><span class="ex">wp</span> plugin list --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span> --update=available --format=count<span class="va">)</span></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$UPDATES</span><span class="st">"</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"  </span><span class="va">$url</span><span class="st">: </span><span class="va">$UPDATES</span><span class="st"> plugin updates available"</span></span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/support/article/multisite-network-administration/#network-admin-menu">Multisite network analytics</a>.</p>



<h3 class="wp-block-heading" id="backup-clone">Backup and Clone Operations</h3>



<p>Backup individual sites or clone across network.</p>



<h4 class="wp-block-heading" id="individual-site-backup">Individual Site Backup</h4>



<div class="sourceCode" id="cb13">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true"></a><span class="co"># backup-multisite-site.sh</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a><span class="va">SITE_ID=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true"></a><span class="va">BACKUP_DIR=</span><span class="st">"/backups/multisite"</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true"></a></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$SITE_ID</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;site_id&gt;"</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true"></a></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true"></a><span class="va">SITE_URL=$(</span><span class="ex">wp</span> site list --blog_id=<span class="st">"</span><span class="va">$SITE_ID</span><span class="st">"</span> --field=url<span class="va">)</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true"></a><span class="va">DATE=$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true"></a></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backing up site: </span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true"></a></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">"</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true"></a></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true"></a><span class="co"># Export database for specific site</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/site-</span><span class="va">${SITE_ID}</span><span class="st">-</span><span class="va">${DATE}</span><span class="st">.sql.gz"</span> --url=<span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true"></a></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true"></a><span class="co"># Backup uploads directory</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-d</span> <span class="st">"wp-content/uploads/sites/</span><span class="va">$SITE_ID</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true"></a>    <span class="fu">tar</span> -czf <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/uploads-</span><span class="va">${SITE_ID}</span><span class="st">-</span><span class="va">${DATE}</span><span class="st">.tar.gz"</span> <span class="kw">\</span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true"></a>        <span class="st">"wp-content/uploads/sites/</span><span class="va">$SITE_ID</span><span class="st">"</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true"></a></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Backup complete: </span><span class="va">$BACKUP_DIR</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="clone-site-within-network">Clone Site Within Network</h4>



<div class="sourceCode" id="cb14">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true"></a><span class="co"># clone-multisite-site.sh</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true"></a><span class="va">SOURCE_SITE_ID=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true"></a><span class="va">NEW_SLUG=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true"></a><span class="va">NEW_TITLE=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true"></a></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$SOURCE_SITE_ID</span><span class="st">"</span><span class="bu"> ]</span> <span class="kw">||</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$NEW_SLUG</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;source_site_id&gt; &lt;new_slug&gt; &lt;new_title&gt;"</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true"></a></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true"></a><span class="va">SOURCE_URL=$(</span><span class="ex">wp</span> site list --blog_id=<span class="st">"</span><span class="va">$SOURCE_SITE_ID</span><span class="st">"</span> --field=url<span class="va">)</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true"></a></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Cloning site: </span><span class="va">$SOURCE_URL</span><span class="st"> to /</span><span class="va">$NEW_SLUG</span><span class="st">"</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true"></a></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true"></a><span class="co"># Export source site</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true"></a><span class="va">TEMP_SQL=</span><span class="st">"/tmp/clone-</span><span class="va">$SOURCE_SITE_ID</span><span class="st">.sql"</span></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"</span><span class="va">$TEMP_SQL</span><span class="st">"</span> --url=<span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true"></a></span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true"></a><span class="co"># Create new site</span></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true"></a><span class="va">NEW_SITE_ID=$(</span><span class="ex">wp</span> site create <span class="kw">\</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true"></a>    <span class="ex">--slug</span>=<span class="st">"</span><span class="va">$NEW_SLUG</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true"></a>    <span class="ex">--title</span>=<span class="st">"</span><span class="va">$NEW_TITLE</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true"></a>    <span class="ex">--email</span>=<span class="st">"admin@example.com"</span> <span class="kw">\</span></span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true"></a>    <span class="ex">--porcelain</span><span class="va">)</span></span>
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true"></a></span>
<span id="cb14-28"><a href="#cb14-28" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ New site created (ID: </span><span class="va">$NEW_SITE_ID</span><span class="st">)"</span></span>
<span id="cb14-29"><a href="#cb14-29" aria-hidden="true"></a></span>
<span id="cb14-30"><a href="#cb14-30" aria-hidden="true"></a><span class="co"># Import database to new site</span></span>
<span id="cb14-31"><a href="#cb14-31" aria-hidden="true"></a><span class="co"># Note: This requires custom SQL modification for multisite table prefixes</span></span>
<span id="cb14-32"><a href="#cb14-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Manual step required: Modify SQL dump table prefixes from wp_</span><span class="va">${SOURCE_SITE_ID}</span><span class="st">_ to wp_</span><span class="va">${NEW_SITE_ID}</span><span class="st">_"</span></span>
<span id="cb14-33"><a href="#cb14-33" aria-hidden="true"></a></span>
<span id="cb14-34"><a href="#cb14-34" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Clone preparation complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="network-maintenance">Network Maintenance Automation</h3>



<p>Automate routine network maintenance tasks.</p>



<h4 class="wp-block-heading" id="automated-maintenance-script">Automated Maintenance Script</h4>



<div class="sourceCode" id="cb15">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true"></a><span class="co"># multisite-maintenance.sh</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"/var/log/multisite-maintenance.log"</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true"></a></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true"></a></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Multisite Maintenance Started ==="</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true"></a></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true"></a><span class="co"># Update WordPress core on all sites</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Updating WordPress core..."</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true"></a><span class="ex">wp</span> core update --network</span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true"></a></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true"></a><span class="co"># Update all plugins across network</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Updating plugins network-wide..."</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"Updating plugins on: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true"></a>    <span class="ex">wp</span> plugin update --all --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span> <span class="op">2&gt;&amp;1</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true"></a></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true"></a><span class="co"># Update all themes</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Updating themes network-wide..."</span></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"Updating themes on: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true"></a>    <span class="ex">wp</span> theme update --all --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span> <span class="op">2&gt;&amp;1</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true"></a></span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Clearing caches..."</span></span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true"></a>    <span class="ex">wp</span> cache flush --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb15-34"><a href="#cb15-34" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb15-35"><a href="#cb15-35" aria-hidden="true"></a></span>
<span id="cb15-36"><a href="#cb15-36" aria-hidden="true"></a><span class="co"># Optimize databases</span></span>
<span id="cb15-37"><a href="#cb15-37" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Optimizing databases..."</span></span>
<span id="cb15-38"><a href="#cb15-38" aria-hidden="true"></a><span class="ex">wp</span> db optimize</span>
<span id="cb15-39"><a href="#cb15-39" aria-hidden="true"></a></span>
<span id="cb15-40"><a href="#cb15-40" aria-hidden="true"></a><span class="co"># Clean up spam/trash</span></span>
<span id="cb15-41"><a href="#cb15-41" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Cleaning up spam and trash..."</span></span>
<span id="cb15-42"><a href="#cb15-42" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">url</span> in <span class="va">$(</span><span class="ex">wp</span> site list --field=url<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb15-43"><a href="#cb15-43" aria-hidden="true"></a>    <span class="ex">wp</span> post delete <span class="va">$(</span><span class="ex">wp</span> post list --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span> --post_status=trash --format=ids<span class="va">)</span> --force</span>
<span id="cb15-44"><a href="#cb15-44" aria-hidden="true"></a>    <span class="ex">wp</span> comment delete <span class="va">$(</span><span class="ex">wp</span> comment list --url=<span class="st">"</span><span class="va">$url</span><span class="st">"</span> --status=spam --format=ids<span class="va">)</span> --force</span>
<span id="cb15-45"><a href="#cb15-45" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb15-46"><a href="#cb15-46" aria-hidden="true"></a></span>
<span id="cb15-47"><a href="#cb15-47" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Maintenance Complete ==="</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="scheduled-network-maintenance">Scheduled Network Maintenance</h4>



<div class="sourceCode" id="cb16">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true"></a><span class="co"># Add to crontab: crontab -e</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true"></a><span class="co"># Weekly network maintenance (Sundays at 2 AM)</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true"></a><span class="ex">0</span> 2 * * 0 /usr/local/bin/multisite-maintenance.sh</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true"></a><span class="co"># Daily network health report</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true"></a><span class="ex">0</span> 8 * * * /usr/local/bin/network-health-report.sh</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true"></a></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true"></a><span class="co"># Monthly user audit across network</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true"></a><span class="ex">0</span> 9 1 * * /usr/local/bin/network-user-report.sh <span class="kw">|</span> <span class="ex">mail</span> -s <span class="st">"Monthly Network User Report"</span> admin@example.com</span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have comprehensive WordPress Multisite network management capabilities with WP-CLI.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: Basic operations</p>



<ul class="wp-block-list">
<li>Create and manage sites</li>



<li>Understand network commands</li>



<li>Practice bulk operations</li>
</ul>



<p><strong>Week 2</strong>: User management</p>



<ul class="wp-block-list">
<li>Add users across network</li>



<li>Manage roles and permissions</li>



<li>Configure super admins</li>
</ul>



<p><strong>Week 3</strong>: Automation</p>



<ul class="wp-block-list">
<li>Build provisioning scripts</li>



<li>Automate maintenance tasks</li>



<li>Create reporting systems</li>
</ul>



<p><strong>Week 4</strong>: Production scaling</p>



<ul class="wp-block-list">
<li>Optimize large networks</li>



<li>Implement monitoring</li>



<li>Backup and disaster recovery</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Multi-Network WordPress</a></strong> &#8211; Networks of networks</li>



<li><strong><a href="#">Multisite Performance Optimization</a></strong> &#8211; Scale to thousands of sites</li>



<li><strong><a href="#">Custom Network Plugins</a></strong> &#8211; Build network-specific functionality</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download Multisite scripts</a></strong> including:</p>



<ul class="wp-block-list">
<li>Site provisioning automation</li>



<li>Network management tools</li>



<li>Reporting templates</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>Multisite best practices</li>



<li>Network scaling strategies</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>WordPress Multisite network management with WP-CLI transforms tedious manual operations into automated workflows—enabling efficient management of networks with hundreds or thousands of sites.</p>



<p>What we covered:</p>



<p>✅ Essential Multisite network commands <br>✅ Bulk site creation and provisioning <br>✅ Network-wide plugin and theme management <br>✅ User management across multiple sites <br>✅ Comprehensive network reporting <br>✅ Automated maintenance workflows</p>



<p>Master these techniques, and you’ll manage large WordPress Multisite networks effortlessly—provisioning sites instantly, automating updates, and monitoring health across entire networks.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">Multisite performance optimization</a> or <a href="#">enterprise WordPress architecture</a>.</p>



<p><strong>Questions about WordPress Multisite management?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other network administrators.</p>
<p>The post <a href="https://wpclimastery.com/blog/wordpress-multisite-network-management-with-wp-cli-complete-guide/">WordPress Multisite Network Management with WP-CLI: Complete Guide</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Automate WordPress Content with AI APIs and WP-CLI (Claude, OpenAI)</title>
		<link>https://wpclimastery.com/blog/automate-wordpress-content-with-ai-apis-and-wp-cli-claude-openai/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Fri, 20 Feb 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[API Integration Tutorials]]></category>
		<category><![CDATA[ai wordpress content]]></category>
		<category><![CDATA[automated content generation]]></category>
		<category><![CDATA[claude api wordpress]]></category>
		<category><![CDATA[openai wordpress]]></category>
		<category><![CDATA[wp-cli ai automation]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=163</guid>

					<description><![CDATA[<p>Creating quality WordPress content at scale is time-consuming—researching topics, writing articles, editing drafts, and formatting posts manually limits how much you can publish. Writers spend hours producing content that AI...</p>
<p>The post <a href="https://wpclimastery.com/blog/automate-wordpress-content-with-ai-apis-and-wp-cli-claude-openai/">Automate WordPress Content with AI APIs and WP-CLI (Claude, OpenAI)</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Creating quality WordPress content at scale is time-consuming—researching topics, writing articles, editing drafts, and formatting posts manually limits how much you can publish. Writers spend hours producing content that AI could generate in minutes.</p>



<p>AI-powered content generation with WP-CLI automates WordPress publishing—generate articles from prompts, create variations, translate content, optimize for SEO, and publish directly to WordPress. Combine Claude API or OpenAI with WP-CLI for scalable content workflows.</p>



<p>In this guide, you’ll learn to build AI content generation systems for WordPress using WP-CLI, with ethical guidelines, API integration patterns, and automation workflows for responsible AI-assisted publishing.</p>



<h3 class="wp-block-heading" id="ethics">AI Content Generation Ethics</h3>



<p>Before building AI content systems, understand ethical implications and responsible use.</p>



<h4 class="wp-block-heading" id="ethical-considerations">Ethical Considerations</h4>



<p><strong>Transparency</strong>: Disclose AI-generated content to readers when appropriate.</p>



<p><strong>Quality control</strong>: Review and edit AI output before publishing.</p>



<p><strong>Originality</strong>: Ensure content doesn’t plagiarize or duplicate existing work.</p>



<p><strong>Accuracy</strong>: Verify facts, statistics, and claims in AI-generated content.</p>



<p><strong>Human value</strong>: Use AI to augment human creativity, not replace it entirely.</p>



<h4 class="wp-block-heading" id="responsible-ai-content-guidelines">Responsible AI Content Guidelines</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="co"># Best practices for AI-generated WordPress content</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a><span class="ex">1.</span> Human oversight required</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a>   <span class="ex">-</span> Review all AI content before publishing</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a>   <span class="ex">-</span> Edit for accuracy, tone, and brand voice</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a>   <span class="ex">-</span> Add human expertise and insights</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a><span class="ex">2.</span> Disclosure when appropriate</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a>   <span class="ex">-</span> Consider adding AI disclosure for transparency</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a>   <span class="ex">-</span> Follow FTC guidelines for automated content</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a><span class="ex">3.</span> Quality over quantity</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a>   <span class="ex">-</span> Don<span class="st">'t publish low-quality AI content at scale</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a><span class="st">   - Maintain editorial standards</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true"></a></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true"></a><span class="st">4. Respect copyrights</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true"></a><span class="st">   - Don'</span>t train on or reproduce copyrighted material</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true"></a>   <span class="ex">-</span> Verify AI output is original</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true"></a><span class="ex">5.</span> Value to readers</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true"></a>   <span class="ex">-</span> Ensure content serves reader needs</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true"></a>   <span class="ex">-</span> Provide genuine value, not just SEO filler</span></code></pre>
</div>



<p>Learn about <a href="https://www.ftc.gov/business-guidance/blog/2023/02/keep-your-ai-claims-check">AI content ethics</a> from the FTC.</p>



<h3 class="wp-block-heading" id="claude-api">Claude API Integration</h3>



<p>Integrate Anthropic’s Claude API with WP-CLI for content generation.</p>



<h4 class="wp-block-heading" id="claude-api-setup">Claude API Setup</h4>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="co"># Install dependencies</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a><span class="ex">pip</span> install anthropic</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a><span class="co"># Set API key</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a><span class="bu">export</span> <span class="va">ANTHROPIC_API_KEY=</span><span class="st">"your-api-key-here"</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a><span class="co"># Test connection</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a><span class="ex">python</span> -c <span class="st">"import anthropic; client = anthropic.Anthropic(); print('Connected')"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="generate-content-with-claude">Generate Content with Claude</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">#!/usr/bin/env python3</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># generate-with-claude.py</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="im">import</span> anthropic</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a><span class="im">import</span> sys</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="im">import</span> os</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a><span class="kw">def</span> generate_article(topic, target_words<span class="op">=</span><span class="dv">1000</span>):</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a>    client <span class="op">=</span> anthropic.Anthropic(api_key<span class="op">=</span>os.environ.get(<span class="st">"ANTHROPIC_API_KEY"</span>))</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a>    prompt <span class="op">=</span> <span class="ss">f"""Write a </span><span class="sc">{</span>target_words<span class="sc">}</span><span class="ss">-word informative blog post about: </span><span class="sc">{</span>topic<span class="sc">}</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a><span class="ss">Include:</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a><span class="ss">- Engaging introduction</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a><span class="ss">- 3-5 main sections with H2 headings</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a><span class="ss">- Practical examples</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a><span class="ss">- Conclusion with key takeaways</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a><span class="ss">Format in markdown."""</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a>    message <span class="op">=</span> client.messages.create(</span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a>        model<span class="op">=</span><span class="st">"claude-3-5-sonnet-20241022"</span>,</span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a>        max_tokens<span class="op">=</span><span class="dv">4096</span>,</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a>        messages<span class="op">=</span>[</span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a>            {<span class="st">"role"</span>: <span class="st">"user"</span>, <span class="st">"content"</span>: prompt}</span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true"></a>        ]</span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true"></a>    )</span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a>    <span class="cf">return</span> message.content[<span class="dv">0</span>].text</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true"></a>    topic <span class="op">=</span> sys.argv[<span class="dv">1</span>] <span class="cf">if</span> <span class="bu">len</span>(sys.argv) <span class="op">&gt;</span> <span class="dv">1</span> <span class="cf">else</span> <span class="st">"WordPress automation"</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true"></a></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true"></a>    <span class="bu">print</span>(generate_article(topic))</span></code></pre>
</div>



<p>Usage:</p>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="ex">python</span> generate-with-claude.py <span class="st">"WP-CLI best practices"</span> <span class="op">&gt;</span> article.md</span></code></pre>
</div>



<h4 class="wp-block-heading" id="publish-to-wordpress">Publish to WordPress</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="co"># ai-to-wordpress.sh - Generate and publish AI content</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">TOPIC=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="va">CATEGORY_ID=</span><span class="st">"</span><span class="va">${2:-</span>1<span class="va">}</span><span class="st">"</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$TOPIC</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;topic&gt; [category_id]"</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Generating content for: </span><span class="va">$TOPIC</span><span class="st">"</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a><span class="co"># Generate content with Claude</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a><span class="va">CONTENT=$(</span><span class="ex">python</span> generate-with-claude.py <span class="st">"</span><span class="va">$TOPIC</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a><span class="co"># Create WordPress post as draft for review</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a><span class="va">POST_ID=$(</span><span class="ex">wp</span> post create <span class="kw">\</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a>    <span class="ex">--post_title</span>=<span class="st">"</span><span class="va">$TOPIC</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true"></a>    <span class="ex">--post_content</span>=<span class="st">"</span><span class="va">$CONTENT</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true"></a>    <span class="ex">--post_status</span>=draft <span class="kw">\</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true"></a>    <span class="ex">--post_category</span>=<span class="va">$CATEGORY_ID</span> <span class="kw">\</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true"></a>    <span class="ex">--porcelain</span><span class="va">)</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true"></a></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Draft created: Post ID </span><span class="va">$POST_ID</span><span class="st">"</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Review at: </span><span class="va">$(</span><span class="ex">wp</span> option get siteurl<span class="va">)</span><span class="st">/wp-admin/post.php?post=</span><span class="va">$POST_ID</span><span class="st">&amp;action=edit"</span></span></code></pre>
</div>



<p>Learn about <a href="https://docs.anthropic.com/claude/reference/getting-started-with-the-api">Claude API</a>.</p>



<h3 class="wp-block-heading" id="openai-integration">OpenAI Integration</h3>



<p>Use OpenAI’s GPT models for WordPress content generation.</p>



<h4 class="wp-block-heading" id="openai-setup">OpenAI Setup</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co"># Install OpenAI library</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="ex">pip</span> install openai</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="co"># Set API key</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="bu">export</span> <span class="va">OPENAI_API_KEY=</span><span class="st">"your-api-key-here"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="generate-with-gpt-4">Generate with GPT-4</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co">#!/usr/bin/env python3</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="co"># generate-with-openai.py</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a><span class="im">from</span> openai <span class="im">import</span> OpenAI</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="im">import</span> sys</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a><span class="im">import</span> os</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a><span class="kw">def</span> generate_article(topic, model<span class="op">=</span><span class="st">"gpt-4"</span>):</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a>    client <span class="op">=</span> OpenAI(api_key<span class="op">=</span>os.environ.get(<span class="st">"OPENAI_API_KEY"</span>))</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a>    response <span class="op">=</span> client.chat.completions.create(</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a>        model<span class="op">=</span>model,</span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a>        messages<span class="op">=</span>[</span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a>            {<span class="st">"role"</span>: <span class="st">"system"</span>, <span class="st">"content"</span>: <span class="st">"You are a professional content writer creating high-quality WordPress blog posts."</span>},</span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a>            {<span class="st">"role"</span>: <span class="st">"user"</span>, <span class="st">"content"</span>: <span class="ss">f"Write a comprehensive 1000-word blog post about: </span><span class="sc">{</span>topic<span class="sc">}</span><span class="ss">. Include clear headings, practical examples, and actionable takeaways. Format in markdown."</span>}</span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a>        ],</span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a>        temperature<span class="op">=</span><span class="fl">0.7</span>,</span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a>        max_tokens<span class="op">=</span><span class="dv">2000</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a>    )</span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a>    <span class="cf">return</span> response.choices[<span class="dv">0</span>].message.content</span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a>    topic <span class="op">=</span> sys.argv[<span class="dv">1</span>] <span class="cf">if</span> <span class="bu">len</span>(sys.argv) <span class="op">&gt;</span> <span class="dv">1</span> <span class="cf">else</span> <span class="st">"WordPress development"</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true"></a>    <span class="bu">print</span>(generate_article(topic))</span></code></pre>
</div>



<h4 class="wp-block-heading" id="batch-content-generation">Batch Content Generation</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="co"># batch-generate-content.sh - Generate multiple posts</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a><span class="va">TOPICS_FILE=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$TOPICS_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;topics-file&gt;"</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Topics file should contain one topic per line"</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true"></a><span class="kw">while</span> <span class="bu">read</span> -r <span class="va">TOPIC</span>; <span class="kw">do</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Generating: </span><span class="va">$TOPIC</span><span class="st">"</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a>    <span class="co"># Generate content</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a>    <span class="va">CONTENT=$(</span><span class="ex">python</span> generate-with-claude.py <span class="st">"</span><span class="va">$TOPIC</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true"></a></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a>    <span class="co"># Create draft post</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a>    <span class="va">POST_ID=$(</span><span class="ex">wp</span> post create <span class="kw">\</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a>        <span class="ex">--post_title</span>=<span class="st">"</span><span class="va">$TOPIC</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a>        <span class="ex">--post_content</span>=<span class="st">"</span><span class="va">$CONTENT</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a>        <span class="ex">--post_status</span>=draft <span class="kw">\</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a>        <span class="ex">--porcelain</span><span class="va">)</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ Created draft: </span><span class="va">$POST_ID</span><span class="st">"</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true"></a></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true"></a>    <span class="co"># Rate limiting</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true"></a>    <span class="fu">sleep</span> 2</span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true"></a><span class="kw">done</span> <span class="op">&lt;</span> <span class="st">"</span><span class="va">$TOPICS_FILE</span><span class="st">"</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true"></a></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Batch generation complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="content-enhancement">Content Enhancement</h3>



<p>Use AI to improve existing WordPress content.</p>



<h4 class="wp-block-heading" id="seo-optimization">SEO Optimization</h4>



<div class="sourceCode" id="cb9">
<pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co">#!/usr/bin/env python3</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a><span class="co"># optimize-for-seo.py</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a><span class="im">import</span> anthropic</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a><span class="im">import</span> sys</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a><span class="im">import</span> os</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a><span class="kw">def</span> optimize_content(original_content, focus_keyword):</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a>    client <span class="op">=</span> anthropic.Anthropic(api_key<span class="op">=</span>os.environ.get(<span class="st">"ANTHROPIC_API_KEY"</span>))</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a>    prompt <span class="op">=</span> <span class="ss">f"""Optimize this content for SEO targeting the keyword: </span><span class="sc">{</span>focus_keyword<span class="sc">}</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a><span class="ss">Original content:</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a><span class="sc">{</span>original_content<span class="sc">}</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true"></a><span class="ss">Improve:</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true"></a><span class="ss">- Keyword density (natural placement)</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true"></a><span class="ss">- Meta description suggestion</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true"></a><span class="ss">- H2/H3 headings with keyword variations</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true"></a><span class="ss">- Internal linking opportunities</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true"></a></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true"></a><span class="ss">Provide the optimized version."""</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true"></a></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true"></a>    message <span class="op">=</span> client.messages.create(</span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true"></a>        model<span class="op">=</span><span class="st">"claude-3-5-sonnet-20241022"</span>,</span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true"></a>        max_tokens<span class="op">=</span><span class="dv">4096</span>,</span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true"></a>        messages<span class="op">=</span>[{<span class="st">"role"</span>: <span class="st">"user"</span>, <span class="st">"content"</span>: prompt}]</span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true"></a>    )</span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true"></a></span>
<span id="cb9-30"><a href="#cb9-30" aria-hidden="true"></a>    <span class="cf">return</span> message.content[<span class="dv">0</span>].text</span>
<span id="cb9-31"><a href="#cb9-31" aria-hidden="true"></a></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
<span id="cb9-33"><a href="#cb9-33" aria-hidden="true"></a>    <span class="cf">if</span> <span class="bu">len</span>(sys.argv) <span class="op">&lt;</span> <span class="dv">3</span>:</span>
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true"></a>        <span class="bu">print</span>(<span class="st">"Usage: optimize-for-seo.py &lt;post_id&gt; &lt;focus_keyword&gt;"</span>)</span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true"></a>        sys.exit(<span class="dv">1</span>)</span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true"></a></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true"></a>    post_id <span class="op">=</span> sys.argv[<span class="dv">1</span>]</span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true"></a>    keyword <span class="op">=</span> sys.argv[<span class="dv">2</span>]</span>
<span id="cb9-39"><a href="#cb9-39" aria-hidden="true"></a></span>
<span id="cb9-40"><a href="#cb9-40" aria-hidden="true"></a>    <span class="co"># Get original content (would use wp-cli here)</span></span>
<span id="cb9-41"><a href="#cb9-41" aria-hidden="true"></a>    content <span class="op">=</span> sys.stdin.read()</span>
<span id="cb9-42"><a href="#cb9-42" aria-hidden="true"></a></span>
<span id="cb9-43"><a href="#cb9-43" aria-hidden="true"></a>    <span class="bu">print</span>(optimize_content(content, keyword))</span></code></pre>
</div>



<h4 class="wp-block-heading" id="content-expansion">Content Expansion</h4>



<div class="sourceCode" id="cb10">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a><span class="co"># expand-content.sh - Expand short posts with AI</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a><span class="va">MIN_WORDS=</span>300</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a><span class="va">TARGET_WORDS=</span>1000</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a><span class="co"># Find short posts</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a><span class="va">SHORT_POSTS=$(</span><span class="ex">wp</span> post list <span class="kw">\</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a>    <span class="ex">--post_status</span>=publish <span class="kw">\</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a>    <span class="ex">--format</span>=ids <span class="kw">\</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a>    <span class="ex">--fields</span>=ID,post_content <span class="kw">\</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a>    <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">POST_ID</span>; <span class="kw">do</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></a>        <span class="va">WORD_COUNT=$(</span><span class="ex">wp</span> post get <span class="va">$POST_ID</span> --field=post_content <span class="kw">|</span> <span class="fu">wc</span> -w<span class="va">)</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true"></a>        <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$WORD_COUNT</span><span class="st">"</span> <span class="ot">-lt</span> <span class="st">"</span><span class="va">$MIN_WORDS</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"</span><span class="va">$POST_ID</span><span class="st">"</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true"></a>    <span class="kw">done</span><span class="va">)</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true"></a></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">POST_ID</span> in <span class="va">$SHORT_POSTS</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Expanding post: </span><span class="va">$POST_ID</span><span class="st">"</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true"></a></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true"></a>    <span class="va">TITLE=$(</span><span class="ex">wp</span> post get <span class="va">$POST_ID</span> --field=post_title<span class="va">)</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true"></a>    <span class="va">CONTENT=$(</span><span class="ex">wp</span> post get <span class="va">$POST_ID</span> --field=post_content<span class="va">)</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true"></a></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true"></a>    <span class="co"># Generate expanded version</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true"></a>    <span class="va">EXPANDED=$(</span><span class="ex">python</span> -c <span class="st">"</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true"></a><span class="st">import anthropic, os</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true"></a><span class="st">client = anthropic.Anthropic(api_key=os.environ.get('ANTHROPIC_API_KEY'))</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true"></a><span class="st">message = client.messages.create(</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true"></a><span class="st">    model='claude-3-5-sonnet-20241022',</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true"></a><span class="st">    max_tokens=2048,</span></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true"></a><span class="st">    messages=[{</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true"></a><span class="st">        'role': 'user',</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true"></a><span class="st">        'content': f'''Expand this article to approximately </span><span class="va">$TARGET_WORDS</span><span class="st"> words while maintaining quality:</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true"></a></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true"></a><span class="st">Title: </span><span class="va">$TITLE</span></span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true"></a></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true"></a><span class="st">Current content:</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true"></a><span class="va">$CONTENT</span></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true"></a></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true"></a><span class="st">Add more detail, examples, and value while staying on topic.'''</span></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true"></a><span class="st">    }]</span></span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true"></a><span class="st">)</span></span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true"></a><span class="st">print(message.content[0].text)</span></span>
<span id="cb10-45"><a href="#cb10-45" aria-hidden="true"></a><span class="st">"</span><span class="va">)</span></span>
<span id="cb10-46"><a href="#cb10-46" aria-hidden="true"></a></span>
<span id="cb10-47"><a href="#cb10-47" aria-hidden="true"></a>    <span class="co"># Save as revision (create new draft for review)</span></span>
<span id="cb10-48"><a href="#cb10-48" aria-hidden="true"></a>    <span class="ex">wp</span> post create <span class="kw">\</span></span>
<span id="cb10-49"><a href="#cb10-49" aria-hidden="true"></a>        <span class="ex">--post_title</span>=<span class="st">"</span><span class="va">$TITLE</span><span class="st"> (Expanded)"</span> <span class="kw">\</span></span>
<span id="cb10-50"><a href="#cb10-50" aria-hidden="true"></a>        <span class="ex">--post_content</span>=<span class="st">"</span><span class="va">$EXPANDED</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb10-51"><a href="#cb10-51" aria-hidden="true"></a>        <span class="ex">--post_status</span>=draft</span>
<span id="cb10-52"><a href="#cb10-52" aria-hidden="true"></a></span>
<span id="cb10-53"><a href="#cb10-53" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ Expanded version created for review"</span></span>
<span id="cb10-54"><a href="#cb10-54" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="automated-workflows">Automated Publishing Workflows</h3>



<p>Build complete AI-powered content pipelines.</p>



<h4 class="wp-block-heading" id="daily-auto-publish-system">Daily Auto-Publish System</h4>



<div class="sourceCode" id="cb11">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="co"># daily-ai-content.sh - Generate and publish content daily</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a><span class="va">TOPICS=(</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a>    <span class="st">"WordPress security best practices"</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a>    <span class="st">"WP-CLI productivity tips"</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a>    <span class="st">"WordPress performance optimization"</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a>    <span class="st">"Content management automation"</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a>)</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true"></a><span class="co"># Select random topic</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true"></a><span class="va">TOPIC=</span><span class="st">"</span><span class="va">${TOPICS[$RANDOM % ${#TOPICS[@]}]}</span><span class="st">"</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true"></a></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Generating daily content: </span><span class="va">$TOPIC</span><span class="st">"</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true"></a></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true"></a><span class="co"># Generate with AI</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true"></a><span class="va">CONTENT=$(</span><span class="ex">python</span> generate-with-claude.py <span class="st">"</span><span class="va">$TOPIC</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true"></a></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true"></a><span class="co"># Add disclaimer</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true"></a><span class="va">DISCLAIMER=</span><span class="st">"&lt;em&gt;Note: This article was generated with AI assistance and reviewed by our editorial team.&lt;/em&gt;"</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true"></a></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true"></a><span class="va">FULL_CONTENT=</span><span class="st">"</span><span class="va">${CONTENT}</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true"></a></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true"></a></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true"></a><span class="va">${DISCLAIMER}</span><span class="st">"</span></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true"></a></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true"></a><span class="co"># Create post</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true"></a><span class="va">POST_ID=$(</span><span class="ex">wp</span> post create <span class="kw">\</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true"></a>    <span class="ex">--post_title</span>=<span class="st">"</span><span class="va">$TOPIC</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true"></a>    <span class="ex">--post_content</span>=<span class="st">"</span><span class="va">$FULL_CONTENT</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true"></a>    <span class="ex">--post_status</span>=draft <span class="kw">\</span></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true"></a>    <span class="ex">--post_category</span>=5 <span class="kw">\</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true"></a>    <span class="ex">--tags_input</span>=<span class="st">"ai-generated,automation"</span> <span class="kw">\</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true"></a>    <span class="ex">--porcelain</span><span class="va">)</span></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true"></a></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true"></a><span class="co"># Set featured image (from Unsplash API - separate integration)</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true"></a><span class="co"># Add meta fields for tracking</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true"></a><span class="ex">wp</span> post meta add <span class="va">$POST_ID</span> ai_generated <span class="st">"true"</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true"></a><span class="ex">wp</span> post meta add <span class="va">$POST_ID</span> generation_date <span class="st">"</span><span class="va">$(</span><span class="fu">date</span> +%Y-%m-%d<span class="va">)</span><span class="st">"</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true"></a></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Draft created: </span><span class="va">$POST_ID</span><span class="st">"</span></span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Review and publish at: </span><span class="va">$(</span><span class="ex">wp</span> option get siteurl<span class="va">)</span><span class="st">/wp-admin/post.php?post=</span><span class="va">$POST_ID</span><span class="st">&amp;action=edit"</span></span></code></pre>
</div>



<p>Schedule with cron:</p>



<div class="sourceCode" id="cb12">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a><span class="co"># Run daily at 8 AM</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a><span class="ex">0</span> 8 * * * /usr/local/bin/daily-ai-content.sh</span></code></pre>
</div>



<h4 class="wp-block-heading" id="content-translation">Content Translation</h4>



<div class="sourceCode" id="cb13">
<pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a><span class="co">#!/usr/bin/env python3</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true"></a><span class="co"># translate-post.py - Translate WordPress posts with AI</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a><span class="im">import</span> anthropic</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true"></a><span class="im">import</span> sys</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true"></a><span class="im">import</span> os</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true"></a></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true"></a><span class="kw">def</span> translate_content(content, target_language):</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true"></a>    client <span class="op">=</span> anthropic.Anthropic(api_key<span class="op">=</span>os.environ.get(<span class="st">"ANTHROPIC_API_KEY"</span>))</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true"></a></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true"></a>    message <span class="op">=</span> client.messages.create(</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true"></a>        model<span class="op">=</span><span class="st">"claude-3-5-sonnet-20241022"</span>,</span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true"></a>        max_tokens<span class="op">=</span><span class="dv">4096</span>,</span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true"></a>        messages<span class="op">=</span>[{</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true"></a>            <span class="st">"role"</span>: <span class="st">"user"</span>,</span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true"></a>            <span class="st">"content"</span>: <span class="ss">f"Translate this content to </span><span class="sc">{</span>target_language<span class="sc">}</span><span class="ss">. Maintain formatting and structure:</span><span class="ch">\n\n</span><span class="sc">{</span>content<span class="sc">}</span><span class="ss">"</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true"></a>        }]</span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true"></a>    )</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true"></a></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true"></a>    <span class="cf">return</span> message.content[<span class="dv">0</span>].text</span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true"></a></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true"></a>    <span class="cf">if</span> <span class="bu">len</span>(sys.argv) <span class="op">&lt;</span> <span class="dv">3</span>:</span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true"></a>        <span class="bu">print</span>(<span class="st">"Usage: translate-post.py &lt;post_id&gt; &lt;language&gt;"</span>)</span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true"></a>        sys.exit(<span class="dv">1</span>)</span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true"></a></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true"></a>    post_id <span class="op">=</span> sys.argv[<span class="dv">1</span>]</span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true"></a>    language <span class="op">=</span> sys.argv[<span class="dv">2</span>]</span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true"></a></span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true"></a>    <span class="co"># Read from stdin</span></span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true"></a>    content <span class="op">=</span> sys.stdin.read()</span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true"></a></span>
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true"></a>    <span class="bu">print</span>(translate_content(content, language))</span></code></pre>
</div>



<p>Usage:</p>



<div class="sourceCode" id="cb14">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true"></a><span class="co"># Translate post to Spanish</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true"></a><span class="ex">wp</span> post get 123 --field=post_content <span class="kw">|</span> <span class="ex">python</span> translate-post.py 123 <span class="st">"Spanish"</span> <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true"></a><span class="ex">wp</span> post create --post_title=<span class="st">"Translated Post"</span> --post_content=-</span></code></pre>
</div>



<h3 class="wp-block-heading" id="quality-control">Quality Control</h3>



<p>Implement checks to ensure AI content quality.</p>



<h4 class="wp-block-heading" id="content-review-checklist">Content Review Checklist</h4>



<div class="sourceCode" id="cb15">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true"></a><span class="co"># review-ai-content.sh - Quality check for AI posts</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true"></a><span class="va">POST_ID=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true"></a></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Reviewing AI-generated post: </span><span class="va">$POST_ID</span><span class="st">"</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true"></a></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true"></a><span class="co"># Check word count</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true"></a><span class="va">WORD_COUNT=$(</span><span class="ex">wp</span> post get <span class="va">$POST_ID</span> --field=post_content <span class="kw">|</span> <span class="fu">wc</span> -w<span class="va">)</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Word count: </span><span class="va">$WORD_COUNT</span><span class="st">"</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true"></a></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$WORD_COUNT</span><span class="st">"</span> <span class="ot">-lt</span> 300<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"⚠ Content too short"</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true"></a></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true"></a><span class="co"># Check for common AI phrases</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true"></a><span class="va">CONTENT=$(</span><span class="ex">wp</span> post get <span class="va">$POST_ID</span> --field=post_content<span class="va">)</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true"></a></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true"></a><span class="va">AI_PHRASES=(</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true"></a>    <span class="st">"as an AI"</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true"></a>    <span class="st">"I don't have"</span></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true"></a>    <span class="st">"I cannot"</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true"></a>    <span class="st">"my knowledge cutoff"</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true"></a>)</span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true"></a></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">PHRASE</span> in <span class="st">"</span><span class="va">${AI_PHRASES[@]}</span><span class="st">"</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true"></a>    <span class="kw">if</span> <span class="bu">echo</span> <span class="st">"</span><span class="va">$CONTENT</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">grep</span> -qi <span class="st">"</span><span class="va">$PHRASE</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"⚠ Found AI artifact: '</span><span class="va">$PHRASE</span><span class="st">'"</span></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true"></a></span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true"></a><span class="co"># Check readability</span></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true"></a><span class="va">TITLE=$(</span><span class="ex">wp</span> post get <span class="va">$POST_ID</span> --field=post_title<span class="va">)</span></span>
<span id="cb15-34"><a href="#cb15-34" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="va">${#TITLE}</span> <span class="ot">-gt</span> 60<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb15-35"><a href="#cb15-35" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"⚠ Title too long for SEO"</span></span>
<span id="cb15-36"><a href="#cb15-36" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb15-37"><a href="#cb15-37" aria-hidden="true"></a></span>
<span id="cb15-38"><a href="#cb15-38" aria-hidden="true"></a><span class="co"># Check for images</span></span>
<span id="cb15-39"><a href="#cb15-39" aria-hidden="true"></a><span class="va">IMAGE_COUNT=$(</span><span class="bu">echo</span> <span class="st">"</span><span class="va">$CONTENT</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">grep</span> -c <span class="st">'&lt;img'</span><span class="va">)</span></span>
<span id="cb15-40"><a href="#cb15-40" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$IMAGE_COUNT</span><span class="st">"</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb15-41"><a href="#cb15-41" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"⚠ No images in content"</span></span>
<span id="cb15-42"><a href="#cb15-42" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb15-43"><a href="#cb15-43" aria-hidden="true"></a></span>
<span id="cb15-44"><a href="#cb15-44" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Review complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="cost-management">Cost Management</h3>



<p>Track and control AI API costs.</p>



<h4 class="wp-block-heading" id="api-usage-tracking">API Usage Tracking</h4>



<div class="sourceCode" id="cb16">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true"></a><span class="co"># track-ai-costs.sh</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"/var/log/ai-content-costs.log"</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true"></a><span class="fu">log_generation()</span> <span class="kw">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">model=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">tokens=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">cost=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true"></a></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"</span><span class="va">$(</span><span class="fu">date</span> +%Y-%m-%d<span class="va">)</span><span class="st">,</span><span class="va">$(</span><span class="fu">date</span> +%H:%M:%S<span class="va">)</span><span class="st">,</span><span class="va">$model</span><span class="st">,</span><span class="va">$tokens</span><span class="st">,</span><span class="va">$cost</span><span class="st">"</span> <span class="op">&gt;&gt;</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true"></a></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true"></a><span class="co"># After each generation</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true"></a><span class="ex">log_generation</span> <span class="st">"claude-3-sonnet"</span> <span class="st">"2048"</span> <span class="st">"0.06"</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true"></a></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true"></a><span class="co"># Monthly report</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true"></a><span class="fu">generate_cost_report()</span> <span class="kw">{</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"AI Content Generation Cost Report"</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Month: </span><span class="va">$(</span><span class="fu">date</span> +%Y-%m<span class="va">)</span><span class="st">"</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"=================================="</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true"></a></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true"></a>    <span class="va">TOTAL_COST=$(</span><span class="fu">awk</span> -F<span class="st">','</span> <span class="st">'{sum += $5} END {print sum}'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true"></a>    <span class="va">TOTAL_POSTS=$(</span><span class="fu">wc</span> -l <span class="op">&lt;</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true"></a></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Total generations: </span><span class="va">$TOTAL_POSTS</span><span class="st">"</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Total cost: </span><span class="dt">\$</span><span class="va">$TOTAL_COST</span><span class="st">"</span></span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Average per post: </span><span class="dt">\$</span><span class="va">$(</span><span class="bu">echo</span> <span class="st">"scale=2; </span><span class="va">$TOTAL_COST</span><span class="st"> / </span><span class="va">$TOTAL_POSTS</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">bc</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true"></a><span class="kw">}</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have AI-powered content generation capabilities for WordPress.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: Basic integration</p>



<ul class="wp-block-list">
<li>Set up Claude/OpenAI APIs</li>



<li>Generate test content</li>



<li>Publish to WordPress</li>
</ul>



<p><strong>Week 2</strong>: Automation</p>



<ul class="wp-block-list">
<li>Build generation scripts</li>



<li>Schedule automated publishing</li>



<li>Implement quality checks</li>
</ul>



<p><strong>Week 3</strong>: Enhancement</p>



<ul class="wp-block-list">
<li>Add SEO optimization</li>



<li>Implement translations</li>



<li>Create content variations</li>
</ul>



<p><strong>Week 4</strong>: Production</p>



<ul class="wp-block-list">
<li>Cost tracking</li>



<li>Quality control systems</li>



<li>Editorial workflows</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Fine-tuning Models</a></strong> &#8211; Custom AI models for your brand</li>



<li><strong><a href="#">Multi-modal Content</a></strong> &#8211; Generate images with text</li>



<li><strong><a href="#">Content Personalization</a></strong> &#8211; AI-driven user targeting</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download AI integration scripts</a></strong> including:</p>



<ul class="wp-block-list">
<li>Complete generation system</li>



<li>Quality control tools</li>



<li>Cost tracking utilities</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>AI content strategies</li>



<li>Automation best practices</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>AI-powered content generation with WP-CLI enables scalable WordPress publishing while maintaining quality through human oversight and ethical practices.</p>



<p>What we covered:</p>



<p>✅ Ethical AI content guidelines <br>✅ Claude and OpenAI API integration <br>✅ Automated content generation workflows <br>✅ Content enhancement and optimization <br>✅ Quality control and review systems <br>✅ Cost tracking and management</p>



<p>Use AI responsibly as a tool to augment human creativity—review all content, ensure accuracy, provide genuine value to readers, and maintain editorial standards.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">content strategy</a> or <a href="#">SEO automation</a>.</p>



<p><strong>Questions about AI content generation for WordPress?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share responsibly with other content creators.</p>
<p>The post <a href="https://wpclimastery.com/blog/automate-wordpress-content-with-ai-apis-and-wp-cli-claude-openai/">Automate WordPress Content with AI APIs and WP-CLI (Claude, OpenAI)</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Automate WordPress Security Scanning and Monitoring with WP-CLI</title>
		<link>https://wpclimastery.com/blog/automate-wordpress-security-scanning-and-monitoring-with-wp-cli/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Sun, 15 Feb 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[WordPress Security & Maintenance]]></category>
		<category><![CDATA[automated security monitoring]]></category>
		<category><![CDATA[security scanning wordpress]]></category>
		<category><![CDATA[wordpress security automation]]></category>
		<category><![CDATA[wordpress vulnerability check]]></category>
		<category><![CDATA[wp-cli security]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=162</guid>

					<description><![CDATA[<p>WordPress security requires constant vigilance—manually checking for plugin vulnerabilities, monitoring file changes, detecting malware, verifying core integrity, and reviewing user permissions. Manual security audits happen infrequently and miss threats between...</p>
<p>The post <a href="https://wpclimastery.com/blog/automate-wordpress-security-scanning-and-monitoring-with-wp-cli/">Automate WordPress Security Scanning and Monitoring with WP-CLI</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>WordPress security requires constant vigilance—manually checking for plugin vulnerabilities, monitoring file changes, detecting malware, verifying core integrity, and reviewing user permissions. Manual security audits happen infrequently and miss threats between checks.</p>



<p>Automated WordPress security scanning with WP-CLI detects vulnerabilities continuously, monitors file integrity, checks for malware patterns, validates checksums, and alerts on suspicious changes. Run comprehensive security scans daily without manual intervention.</p>



<p>In this guide, you’ll build automated WordPress security monitoring systems using WP-CLI, from basic vulnerability checks to production-grade security automation that protects your sites 24/7.</p>



<h3 class="wp-block-heading" id="why-automate">Why Automate WordPress Security?</h3>



<p><a href="https://wordpress.org/support/article/hardening-wordpress/">Manual WordPress security checks</a> don’t provide continuous protection against evolving threats.</p>



<h4 class="wp-block-heading" id="manual-security-limitations">Manual Security Limitations</h4>



<p><strong>Infrequent checks</strong>: Manual audits happen weekly or monthly, leaving gaps.</p>



<p><strong>Human error</strong>: Manual reviews miss subtle security indicators.</p>



<p><strong>Time-consuming</strong>: Comprehensive security audits take hours per site.</p>



<p><strong>No real-time alerts</strong>: Breaches go undetected until the next manual check.</p>



<p><strong>Limited scope</strong>: Can’t check every file, user, and configuration regularly.</p>



<h4 class="wp-block-heading" id="automated-security-benefits">Automated Security Benefits</h4>



<p><strong>Continuous monitoring</strong>: Security checks run automatically every day.</p>



<p><strong>Instant alerts</strong>: Get notified immediately when threats are detected.</p>



<p><strong>Comprehensive coverage</strong>: Scan every file, plugin, theme, and configuration.</p>



<p><strong>Historical tracking</strong>: Log all security events for forensic analysis.</p>



<p><strong>Multi-site management</strong>: Monitor dozens of WordPress sites from one system.</p>



<p>According to <a href="https://sucuri.net/reports/2023-website-security-report/">Sucuri research</a>, automated security monitoring detects breaches 85% faster than manual audits.</p>



<h3 class="wp-block-heading" id="core-integrity">Core File Integrity Verification</h3>



<p>Detect unauthorized modifications to WordPress core files.</p>



<h4 class="wp-block-heading" id="checksum-verification">Checksum Verification</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="co"># verify-core-integrity.sh</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"WordPress Core Integrity Check"</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"==============================="</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a><span class="co"># Verify core file checksums</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> core verify-checksums<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ Core files verified - no modifications detected"</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ ALERT: Core files modified or corrupted"</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Details:"</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a>    <span class="ex">wp</span> core verify-checksums --format=json <span class="kw">|</span> <span class="ex">jq</span> -r <span class="st">'.[] | "  - \(.)"'</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true"></a>    <span class="co"># Send alert</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Core file integrity check failed on </span><span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true"></a>        <span class="ex">mail</span> -s <span class="st">"WordPress Security Alert"</span> admin@example.com</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="automated-daily-verification">Automated Daily Verification</h4>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a><span class="co"># daily-integrity-check.sh</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"/var/log/wp-security.log"</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Starting core integrity check"</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a><span class="co"># Check WordPress core</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> core verify-checksums <span class="op">2&gt;&amp;1</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✗ Core integrity check FAILED"</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true"></a>    <span class="co"># Create detailed report</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true"></a>    <span class="kw">{</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"WordPress Core Integrity Failure"</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"================================="</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Timestamp: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Server: </span><span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"WordPress version: </span><span class="va">$(</span><span class="ex">wp</span> core version<span class="va">)</span><span class="st">"</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Modified files:"</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true"></a>        <span class="ex">wp</span> core verify-checksums <span class="op">2&gt;&amp;1</span> <span class="kw">|</span> <span class="fu">grep</span> <span class="st">"^Error:"</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true"></a>    <span class="kw">}</span> <span class="kw">|</span> <span class="ex">mail</span> -s <span class="st">"URGENT: WordPress Core Modified"</span> security@example.com</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true"></a></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true"></a></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"✓ Core integrity check passed"</span></span></code></pre>
</div>



<p>Learn about <a href="https://developer.wordpress.org/apis/wp-config-php/">WordPress file integrity</a>.</p>



<h3 class="wp-block-heading" id="vulnerability-detection">Plugin and Theme Vulnerability Detection</h3>



<p>Check for known security vulnerabilities in plugins and themes.</p>



<h4 class="wp-block-heading" id="wp-cli-vulnerability-scanner">WP-CLI Vulnerability Scanner</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># scan-vulnerabilities.sh</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"WordPress Vulnerability Scan"</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"============================"</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="co"># Check if WPScan CLI is available</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a><span class="kw">if</span> ! <span class="bu">command</span> -v wpscan <span class="op">&amp;&gt;</span> /dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Installing WPScan..."</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a>    <span class="ex">gem</span> install wpscan</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a><span class="co"># Update WPScan database</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a><span class="ex">wpscan</span> --update</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a><span class="co"># Scan WordPress installation</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a><span class="va">SCAN_RESULTS=$(</span><span class="ex">wpscan</span> --url <span class="st">"</span><span class="va">$(</span><span class="ex">wp</span> option get siteurl<span class="va">)</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a>    <span class="ex">--format</span> json <span class="kw">\</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a>    <span class="ex">--random-user-agent</span> <span class="kw">\</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a>    <span class="ex">--disable-tls-checks</span><span class="va">)</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a><span class="co"># Parse vulnerabilities</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a><span class="va">VULN_COUNT=$(</span><span class="bu">echo</span> <span class="st">"</span><span class="va">$SCAN_RESULTS</span><span class="st">"</span> <span class="kw">|</span> <span class="ex">jq</span> <span class="st">'.plugins | to_entries[] | select(.value.vulnerabilities | length &gt; 0) | .value.vulnerabilities | length'</span> <span class="kw">|</span> <span class="fu">awk</span> <span class="st">'{s+=$1} END {print s}'</span><span class="va">)</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$VULN_COUNT</span><span class="st">"</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ ALERT: </span><span class="va">$VULN_COUNT</span><span class="st"> vulnerabilities detected"</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true"></a></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a>    <span class="co"># Generate detailed report</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"</span><span class="va">$SCAN_RESULTS</span><span class="st">"</span> <span class="kw">|</span> <span class="ex">jq</span> -r <span class="st">'.plugins | to_entries[] | select(.value.vulnerabilities | length &gt; 0) | "Plugin: \(.key)\nVulnerabilities:\n\(.value.vulnerabilities[] | "  - \(.title) (Severity: \(.vuln_type))\n    Fixed in: \(.fixed_in // "No fix available")\n")"'</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ No known vulnerabilities detected"</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="check-plugin-updates-for-security-fixes">Check Plugin Updates for Security Fixes</h4>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="co"># check-security-updates.sh</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Checking for security updates..."</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a><span class="co"># Get plugins with available updates</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a><span class="va">UPDATES=$(</span><span class="ex">wp</span> plugin list --update=available --format=json<span class="va">)</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$UPDATES</span><span class="st">"</span> <span class="ot">!=</span> <span class="st">"[]"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Plugins with available updates:"</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"</span><span class="va">$UPDATES</span><span class="st">"</span> <span class="kw">|</span> <span class="ex">jq</span> -r <span class="st">'.[] | "- \(.name) (Current: \(.version), Available: \(.update_version))"'</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a>    <span class="co"># Check update changelogs for security keywords</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Checking changelogs for security mentions..."</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true"></a></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"</span><span class="va">$UPDATES</span><span class="st">"</span> <span class="kw">|</span> <span class="ex">jq</span> -r <span class="st">'.[].name'</span> <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">PLUGIN</span>; <span class="kw">do</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true"></a>        <span class="va">CHANGELOG=$(</span><span class="ex">wp</span> plugin get <span class="st">"</span><span class="va">$PLUGIN</span><span class="st">"</span> --field=update_changelog <span class="op">2&gt;</span>/dev/null<span class="va">)</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true"></a></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a>        <span class="kw">if</span> <span class="bu">echo</span> <span class="st">"</span><span class="va">$CHANGELOG</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">grep</span> -qi <span class="st">'security\|vulnerability\|xss\|sql injection\|exploit'</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"⚠ SECURITY UPDATE AVAILABLE: </span><span class="va">$PLUGIN</span><span class="st">"</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"  Update immediately using: wp plugin update </span><span class="va">$PLUGIN</span><span class="st">"</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ All plugins up to date"</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/support/article/hardening-wordpress/">WordPress security best practices</a>.</p>



<h3 class="wp-block-heading" id="file-monitoring">File Change Monitoring</h3>



<p>Detect unauthorized file modifications.</p>



<h4 class="wp-block-heading" id="file-integrity-database">File Integrity Database</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="co"># create-file-baseline.sh - Create baseline of file checksums</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">BASELINE_FILE=</span><span class="st">"/var/backups/wp-file-baseline.txt"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="va">WP_PATH=</span><span class="st">"/var/www/html"</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Creating file integrity baseline..."</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$WP_PATH</span><span class="st">"</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a><span class="co"># Generate checksums for all WordPress files</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a><span class="fu">find</span> . -type f <span class="kw">\</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a>    <span class="ex">-not</span> -path <span class="st">"./wp-content/uploads/*"</span> <span class="kw">\</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a>    <span class="ex">-not</span> -path <span class="st">"./wp-content/cache/*"</span> <span class="kw">\</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a>    <span class="ex">-not</span> -path <span class="st">"./wp-content/backup/*"</span> <span class="kw">\</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a>    <span class="ex">-exec</span> md5sum {} <span class="dt">\;</span> <span class="kw">|</span> <span class="fu">sort</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$BASELINE_FILE</span><span class="st">"</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Baseline created: </span><span class="va">$BASELINE_FILE</span><span class="st">"</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Total files: </span><span class="va">$(</span><span class="fu">wc</span> -l <span class="op">&lt;</span> <span class="va">$BASELINE_FILE)</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="detect-file-changes">Detect File Changes</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="co"># detect-file-changes.sh</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="va">BASELINE_FILE=</span><span class="st">"/var/backups/wp-file-baseline.txt"</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="va">WP_PATH=</span><span class="st">"/var/www/html"</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a><span class="va">REPORT_FILE=</span><span class="st">"/tmp/file-changes-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d<span class="va">)</span><span class="st">.txt"</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$BASELINE_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"ERROR: Baseline file not found. Run create-file-baseline.sh first."</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Scanning for file changes..."</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$WP_PATH</span><span class="st">"</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true"></a><span class="co"># Generate current checksums</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a><span class="fu">find</span> . -type f <span class="kw">\</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true"></a>    <span class="ex">-not</span> -path <span class="st">"./wp-content/uploads/*"</span> <span class="kw">\</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true"></a>    <span class="ex">-not</span> -path <span class="st">"./wp-content/cache/*"</span> <span class="kw">\</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true"></a>    <span class="ex">-not</span> -path <span class="st">"./wp-content/backup/*"</span> <span class="kw">\</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true"></a>    <span class="ex">-exec</span> md5sum {} <span class="dt">\;</span> <span class="kw">|</span> <span class="fu">sort</span> <span class="op">&gt;</span> /tmp/current-checksums.txt</span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true"></a></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true"></a><span class="co"># Compare with baseline</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true"></a><span class="kw">{</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"WordPress File Change Report"</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"============================="</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Date: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true"></a></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true"></a>    <span class="co"># Modified files</span></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Modified Files:"</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true"></a>    <span class="fu">comm</span> -13 <span class="st">"</span><span class="va">$BASELINE_FILE</span><span class="st">"</span> /tmp/current-checksums.txt <span class="kw">|</span> <span class="fu">awk</span> <span class="st">'{print $2}'</span> <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">file</span>; <span class="kw">do</span></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true"></a>        <span class="kw">if</span> <span class="fu">grep</span> -q <span class="st">"</span><span class="va">$file</span><span class="st">"</span> <span class="st">"</span><span class="va">$BASELINE_FILE</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"  MODIFIED: </span><span class="va">$file</span><span class="st">"</span></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true"></a></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true"></a></span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true"></a>    <span class="co"># New files</span></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"New Files:"</span></span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true"></a>    <span class="fu">comm</span> -13 <span class="st">"</span><span class="va">$BASELINE_FILE</span><span class="st">"</span> /tmp/current-checksums.txt <span class="kw">|</span> <span class="fu">awk</span> <span class="st">'{print $2}'</span> <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">file</span>; <span class="kw">do</span></span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true"></a>        <span class="kw">if</span> ! <span class="fu">grep</span> -q <span class="st">"</span><span class="va">$file</span><span class="st">"</span> <span class="st">"</span><span class="va">$BASELINE_FILE</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb6-45"><a href="#cb6-45" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"  ADDED: </span><span class="va">$file</span><span class="st">"</span></span>
<span id="cb6-46"><a href="#cb6-46" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb6-47"><a href="#cb6-47" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb6-48"><a href="#cb6-48" aria-hidden="true"></a></span>
<span id="cb6-49"><a href="#cb6-49" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb6-50"><a href="#cb6-50" aria-hidden="true"></a></span>
<span id="cb6-51"><a href="#cb6-51" aria-hidden="true"></a>    <span class="co"># Deleted files</span></span>
<span id="cb6-52"><a href="#cb6-52" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Deleted Files:"</span></span>
<span id="cb6-53"><a href="#cb6-53" aria-hidden="true"></a>    <span class="fu">comm</span> -23 <span class="st">"</span><span class="va">$BASELINE_FILE</span><span class="st">"</span> /tmp/current-checksums.txt <span class="kw">|</span> <span class="fu">awk</span> <span class="st">'{print $2}'</span> <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">file</span>; <span class="kw">do</span></span>
<span id="cb6-54"><a href="#cb6-54" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"  DELETED: </span><span class="va">$file</span><span class="st">"</span></span>
<span id="cb6-55"><a href="#cb6-55" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb6-56"><a href="#cb6-56" aria-hidden="true"></a></span>
<span id="cb6-57"><a href="#cb6-57" aria-hidden="true"></a><span class="kw">}</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb6-58"><a href="#cb6-58" aria-hidden="true"></a></span>
<span id="cb6-59"><a href="#cb6-59" aria-hidden="true"></a><span class="co"># Check if changes detected</span></span>
<span id="cb6-60"><a href="#cb6-60" aria-hidden="true"></a><span class="va">CHANGE_COUNT=$(</span><span class="fu">cat</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">grep</span> -c <span class="st">"MODIFIED:\|ADDED:\|DELETED:"</span><span class="va">)</span></span>
<span id="cb6-61"><a href="#cb6-61" aria-hidden="true"></a></span>
<span id="cb6-62"><a href="#cb6-62" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$CHANGE_COUNT</span><span class="st">"</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb6-63"><a href="#cb6-63" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ ALERT: </span><span class="va">$CHANGE_COUNT</span><span class="st"> file changes detected"</span></span>
<span id="cb6-64"><a href="#cb6-64" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Report: </span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb6-65"><a href="#cb6-65" aria-hidden="true"></a></span>
<span id="cb6-66"><a href="#cb6-66" aria-hidden="true"></a>    <span class="co"># Email report</span></span>
<span id="cb6-67"><a href="#cb6-67" aria-hidden="true"></a>    <span class="ex">mail</span> -s <span class="st">"WordPress File Changes Detected"</span> admin@example.com <span class="op">&lt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb6-68"><a href="#cb6-68" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb6-69"><a href="#cb6-69" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ No file changes detected"</span></span>
<span id="cb6-70"><a href="#cb6-70" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb6-71"><a href="#cb6-71" aria-hidden="true"></a></span>
<span id="cb6-72"><a href="#cb6-72" aria-hidden="true"></a><span class="co"># Cleanup</span></span>
<span id="cb6-73"><a href="#cb6-73" aria-hidden="true"></a><span class="fu">rm</span> /tmp/current-checksums.txt</span></code></pre>
</div>



<h3 class="wp-block-heading" id="malware-scanning">Malware Pattern Scanning</h3>



<p>Detect common malware patterns in WordPress files.</p>



<h4 class="wp-block-heading" id="basic-malware-scanner">Basic Malware Scanner</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="co"># scan-malware.sh - Detect common malware patterns</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a><span class="va">WP_PATH=</span><span class="st">"/var/www/html"</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="va">REPORT_FILE=</span><span class="st">"/tmp/malware-scan-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d<span class="va">)</span><span class="st">.txt"</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"WordPress Malware Scan"</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"======================"</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a><span class="co"># Suspicious patterns to check</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a><span class="bu">declare</span> -a <span class="va">PATTERNS=(</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a>    <span class="st">"eval(base64_decode"</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a>    <span class="st">"eval(gzinflate"</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a>    <span class="st">"eval(str_rot13"</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a>    <span class="st">"system(</span><span class="dt">\$</span><span class="st">_"</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a>    <span class="st">"shell_exec"</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a>    <span class="st">"passthru"</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a>    <span class="st">"base64_decode.*eval"</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a>    <span class="st">"FilesMan"</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a>    <span class="st">"r57shell"</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a>    <span class="st">"c99shell"</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a>    <span class="st">"WSO shell"</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a>)</span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true"></a><span class="kw">{</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Malware Scan Report"</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"==================="</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Date: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Path: </span><span class="va">$WP_PATH</span><span class="st">"</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true"></a></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true"></a>    <span class="kw">for</span> <span class="ex">PATTERN</span> in <span class="st">"</span><span class="va">${PATTERNS[@]}</span><span class="st">"</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Checking for: </span><span class="va">$PATTERN</span><span class="st">"</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true"></a></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true"></a>        <span class="va">MATCHES=$(</span><span class="fu">grep</span> -r -l -i <span class="st">"</span><span class="va">$PATTERN</span><span class="st">"</span> <span class="st">"</span><span class="va">$WP_PATH</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true"></a>            <span class="ex">--exclude-dir</span>=wp-content/uploads <span class="kw">\</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true"></a>            <span class="ex">--exclude-dir</span>=wp-content/cache <span class="kw">\</span></span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true"></a>            <span class="ex">--exclude-dir</span>=node_modules <span class="kw">\</span></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true"></a>            <span class="ex">--include</span>=<span class="st">"*.php"</span> <span class="op">2&gt;</span>/dev/null<span class="va">)</span></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true"></a></span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true"></a>        <span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$MATCHES</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"✗ SUSPICIOUS: Files matching '</span><span class="va">$PATTERN</span><span class="st">':"</span></span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"</span><span class="va">$MATCHES</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">file</span>; <span class="kw">do</span></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true"></a>                <span class="bu">echo</span> <span class="st">"  - </span><span class="va">$file</span><span class="st">"</span></span>
<span id="cb7-45"><a href="#cb7-45" aria-hidden="true"></a>            <span class="kw">done</span></span>
<span id="cb7-46"><a href="#cb7-46" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb7-47"><a href="#cb7-47" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb7-48"><a href="#cb7-48" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb7-49"><a href="#cb7-49" aria-hidden="true"></a></span>
<span id="cb7-50"><a href="#cb7-50" aria-hidden="true"></a><span class="kw">}</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb7-51"><a href="#cb7-51" aria-hidden="true"></a></span>
<span id="cb7-52"><a href="#cb7-52" aria-hidden="true"></a><span class="co"># Check if suspicious files found</span></span>
<span id="cb7-53"><a href="#cb7-53" aria-hidden="true"></a><span class="va">SUSPICIOUS_COUNT=$(</span><span class="fu">grep</span> -c <span class="st">"✗ SUSPICIOUS:"</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span> <span class="kw">||</span> <span class="bu">echo</span> 0<span class="va">)</span></span>
<span id="cb7-54"><a href="#cb7-54" aria-hidden="true"></a></span>
<span id="cb7-55"><a href="#cb7-55" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$SUSPICIOUS_COUNT</span><span class="st">"</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-56"><a href="#cb7-56" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ ALERT: Potential malware detected"</span></span>
<span id="cb7-57"><a href="#cb7-57" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Report: </span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb7-58"><a href="#cb7-58" aria-hidden="true"></a></span>
<span id="cb7-59"><a href="#cb7-59" aria-hidden="true"></a>    <span class="co"># Send alert</span></span>
<span id="cb7-60"><a href="#cb7-60" aria-hidden="true"></a>    <span class="ex">mail</span> -s <span class="st">"URGENT: Potential Malware Detected"</span> security@example.com <span class="op">&lt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb7-61"><a href="#cb7-61" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb7-62"><a href="#cb7-62" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ No malware patterns detected"</span></span>
<span id="cb7-63"><a href="#cb7-63" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="check-for-suspicious-files">Check for Suspicious Files</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="co"># check-suspicious-files.sh</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a><span class="va">WP_PATH=</span><span class="st">"/var/www/html"</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Checking for suspicious files..."</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a><span class="co"># Check for unusual file types in wp-content</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Checking for executable files in wp-content..."</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a><span class="fu">find</span> <span class="st">"</span><span class="va">$WP_PATH</span><span class="st">/wp-content"</span> <span class="kw">\</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a>    <span class="ex">-type</span> f <span class="kw">\</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true"></a>    <span class="dt">\(</span> <span class="ex">-name</span> <span class="st">"*.exe"</span> -o -name <span class="st">"*.sh"</span> -o -name <span class="st">"*.bat"</span> <span class="dt">\)</span> <span class="kw">\</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a>    <span class="ex">-print</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a><span class="co"># Check for PHP files in uploads directory</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Checking for PHP files in uploads..."</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true"></a><span class="fu">find</span> <span class="st">"</span><span class="va">$WP_PATH</span><span class="st">/wp-content/uploads"</span> -name <span class="st">"*.php"</span> -print</span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a><span class="co"># Check for recently modified files (last 24 hours)</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Recently modified PHP files (last 24 hours)..."</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a><span class="fu">find</span> <span class="st">"</span><span class="va">$WP_PATH</span><span class="st">"</span> -name <span class="st">"*.php"</span> -mtime -1 -type f -print</span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a><span class="co"># Check for files with suspicious permissions</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Files with 777 permissions..."</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a><span class="fu">find</span> <span class="st">"</span><span class="va">$WP_PATH</span><span class="st">"</span> -type f -perm 0777 -print</span></code></pre>
</div>



<p>Learn about <a href="https://blog.sucuri.net/2023/03/wordpress-malware-removal-guide.html">WordPress malware detection</a>.</p>



<h3 class="wp-block-heading" id="user-auditing">User Account Security Auditing</h3>



<p>Monitor user accounts for security issues.</p>



<h4 class="wp-block-heading" id="user-security-audit">User Security Audit</h4>



<div class="sourceCode" id="cb9">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a><span class="co"># audit-users.sh</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"WordPress User Security Audit"</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=============================="</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a><span class="co"># Check for users with admin privileges</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Administrator Accounts:"</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a><span class="ex">wp</span> user list --role=administrator --format=table --fields=ID,user_login,user_email,user_registered</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a><span class="va">ADMIN_COUNT=$(</span><span class="ex">wp</span> user list --role=administrator --format=count<span class="va">)</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$ADMIN_COUNT</span><span class="st">"</span> <span class="ot">-gt</span> 3<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"⚠ WARNING: </span><span class="va">$ADMIN_COUNT</span><span class="st"> administrator accounts (recommended: 1-2)"</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true"></a></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true"></a><span class="co"># Check for weak usernames</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Checking for common/weak usernames..."</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true"></a><span class="va">WEAK_USERS=(</span><span class="st">"admin"</span> <span class="st">"administrator"</span> <span class="st">"root"</span> <span class="st">"test"</span> <span class="st">"demo"</span><span class="va">)</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true"></a></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">USERNAME</span> in <span class="st">"</span><span class="va">${WEAK_USERS[@]}</span><span class="st">"</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> user get <span class="st">"</span><span class="va">$USERNAME</span><span class="st">"</span> <span class="op">&amp;&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✗ WARNING: Common username detected: </span><span class="va">$USERNAME</span><span class="st">"</span></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"  Recommended: Delete or rename this account"</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true"></a></span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb9-30"><a href="#cb9-30" aria-hidden="true"></a></span>
<span id="cb9-31"><a href="#cb9-31" aria-hidden="true"></a><span class="co"># Check for inactive admin accounts</span></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Inactive Administrator Accounts (no posts/pages):"</span></span>
<span id="cb9-33"><a href="#cb9-33" aria-hidden="true"></a><span class="ex">wp</span> user list --role=administrator --format=json <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true"></a>    <span class="ex">jq</span> -r <span class="st">'.[] | select(.posts == "0") | "- \(.user_login) (registered: \(.user_registered))"'</span></span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true"></a></span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true"></a></span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true"></a><span class="co"># Check user capabilities</span></span>
<span id="cb9-39"><a href="#cb9-39" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Users with 'delete_users' capability:"</span></span>
<span id="cb9-40"><a href="#cb9-40" aria-hidden="true"></a><span class="ex">wp</span> user list --format=json <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb9-41"><a href="#cb9-41" aria-hidden="true"></a>    <span class="ex">jq</span> -r <span class="st">'.[] | select(.roles[] | contains("administrator")) | .user_login'</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="password-policy-check">Password Policy Check</h4>



<div class="sourceCode" id="cb10">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a><span class="co"># check-password-policy.sh</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Password Policy Check"</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"===================="</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a><span class="co"># This requires custom code to check password strength</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a><span class="co"># WordPress doesn't expose password hashes via WP-CLI for security</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a><span class="co"># Check for recent password changes</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Users who haven't changed password recently:"</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a><span class="co"># This would require custom user meta tracking</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></a></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true"></a><span class="co"># Check for 2FA status (if plugin installed)</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> plugin is-installed two-factor<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"2FA Status:"</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true"></a>    <span class="ex">wp</span> user list --format=json <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true"></a>        <span class="ex">jq</span> -r <span class="st">'.[] | "\(.user_login): \(if .two_factor_enabled then "Enabled" else "DISABLED" end)"'</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true"></a></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true"></a><span class="co"># List users who can install plugins/themes</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Users with plugin/theme installation privileges:"</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true"></a><span class="ex">wp</span> user list --role=administrator,editor --format=csv --fields=user_login,roles</span></code></pre>
</div>



<h3 class="wp-block-heading" id="security-report">Comprehensive Security Report</h3>



<p>Generate complete security assessment reports.</p>



<h4 class="wp-block-heading" id="master-security-script">Master Security Script</h4>



<div class="sourceCode" id="cb11">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="co"># comprehensive-security-check.sh</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a><span class="va">REPORT_FILE=</span><span class="st">"/tmp/wordpress-security-report-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d<span class="va">)</span><span class="st">.txt"</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"/var/log/wp-security.log"</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true"></a><span class="kw">{</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"WordPress Comprehensive Security Report"</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"========================================"</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Generated: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Server: </span><span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true"></a></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true"></a>    <span class="co"># Core integrity</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"1. Core File Integrity"</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"----------------------"</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> core verify-checksums<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ PASS: Core files verified"</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✗ FAIL: Core file modifications detected"</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true"></a></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true"></a>    <span class="co"># Plugin security</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"2. Plugin Security"</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"------------------"</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true"></a>    <span class="va">PLUGIN_UPDATES=$(</span><span class="ex">wp</span> plugin list --update=available --format=count<span class="va">)</span></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Plugins needing updates: </span><span class="va">$PLUGIN_UPDATES</span><span class="st">"</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true"></a></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$PLUGIN_UPDATES</span><span class="st">"</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ PASS: All plugins up to date"</span></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"⚠ WARNING: Plugin updates available"</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true"></a>        <span class="ex">wp</span> plugin list --update=available --format=table --fields=name,version,update_version</span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true"></a></span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true"></a>    <span class="co"># Theme security</span></span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"3. Theme Security"</span></span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"-----------------"</span></span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true"></a>    <span class="va">THEME_UPDATES=$(</span><span class="ex">wp</span> theme list --update=available --format=count<span class="va">)</span></span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Themes needing updates: </span><span class="va">$THEME_UPDATES</span><span class="st">"</span></span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true"></a></span>
<span id="cb11-49"><a href="#cb11-49" aria-hidden="true"></a>    <span class="co"># User accounts</span></span>
<span id="cb11-50"><a href="#cb11-50" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"4. User Account Security"</span></span>
<span id="cb11-51"><a href="#cb11-51" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"------------------------"</span></span>
<span id="cb11-52"><a href="#cb11-52" aria-hidden="true"></a>    <span class="va">ADMIN_COUNT=$(</span><span class="ex">wp</span> user list --role=administrator --format=count<span class="va">)</span></span>
<span id="cb11-53"><a href="#cb11-53" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Administrator accounts: </span><span class="va">$ADMIN_COUNT</span><span class="st">"</span></span>
<span id="cb11-54"><a href="#cb11-54" aria-hidden="true"></a></span>
<span id="cb11-55"><a href="#cb11-55" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$ADMIN_COUNT</span><span class="st">"</span> <span class="ot">-gt</span> 3<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-56"><a href="#cb11-56" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"⚠ WARNING: Too many administrator accounts"</span></span>
<span id="cb11-57"><a href="#cb11-57" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-58"><a href="#cb11-58" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ PASS: Administrator count acceptable"</span></span>
<span id="cb11-59"><a href="#cb11-59" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-60"><a href="#cb11-60" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-61"><a href="#cb11-61" aria-hidden="true"></a></span>
<span id="cb11-62"><a href="#cb11-62" aria-hidden="true"></a>    <span class="co"># SSL/HTTPS check</span></span>
<span id="cb11-63"><a href="#cb11-63" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"5. SSL/HTTPS Configuration"</span></span>
<span id="cb11-64"><a href="#cb11-64" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"--------------------------"</span></span>
<span id="cb11-65"><a href="#cb11-65" aria-hidden="true"></a>    <span class="va">SITE_URL=$(</span><span class="ex">wp</span> option get siteurl<span class="va">)</span></span>
<span id="cb11-66"><a href="#cb11-66" aria-hidden="true"></a>    <span class="kw">if [[</span> <span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span> <span class="ot">==</span> https://*<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb11-67"><a href="#cb11-67" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ PASS: HTTPS enabled"</span></span>
<span id="cb11-68"><a href="#cb11-68" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-69"><a href="#cb11-69" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✗ FAIL: Site not using HTTPS"</span></span>
<span id="cb11-70"><a href="#cb11-70" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-71"><a href="#cb11-71" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-72"><a href="#cb11-72" aria-hidden="true"></a></span>
<span id="cb11-73"><a href="#cb11-73" aria-hidden="true"></a>    <span class="co"># File permissions</span></span>
<span id="cb11-74"><a href="#cb11-74" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"6. File Permissions"</span></span>
<span id="cb11-75"><a href="#cb11-75" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"-------------------"</span></span>
<span id="cb11-76"><a href="#cb11-76" aria-hidden="true"></a>    <span class="va">INSECURE_FILES=$(</span><span class="fu">find</span> . -type f -perm 0777 <span class="kw">|</span> <span class="fu">wc</span> -l<span class="va">)</span></span>
<span id="cb11-77"><a href="#cb11-77" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Files with 777 permissions: </span><span class="va">$INSECURE_FILES</span><span class="st">"</span></span>
<span id="cb11-78"><a href="#cb11-78" aria-hidden="true"></a></span>
<span id="cb11-79"><a href="#cb11-79" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$INSECURE_FILES</span><span class="st">"</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-80"><a href="#cb11-80" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ PASS: No files with overly permissive permissions"</span></span>
<span id="cb11-81"><a href="#cb11-81" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-82"><a href="#cb11-82" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"⚠ WARNING: Insecure file permissions detected"</span></span>
<span id="cb11-83"><a href="#cb11-83" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-84"><a href="#cb11-84" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb11-85"><a href="#cb11-85" aria-hidden="true"></a></span>
<span id="cb11-86"><a href="#cb11-86" aria-hidden="true"></a>    <span class="co"># WordPress version</span></span>
<span id="cb11-87"><a href="#cb11-87" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"7. WordPress Version"</span></span>
<span id="cb11-88"><a href="#cb11-88" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"--------------------"</span></span>
<span id="cb11-89"><a href="#cb11-89" aria-hidden="true"></a>    <span class="va">CURRENT_VERSION=$(</span><span class="ex">wp</span> core version<span class="va">)</span></span>
<span id="cb11-90"><a href="#cb11-90" aria-hidden="true"></a>    <span class="va">LATEST_VERSION=$(</span><span class="ex">wp</span> core check-update --format=json <span class="kw">|</span> <span class="ex">jq</span> -r <span class="st">'.[0].version // empty'</span><span class="va">)</span></span>
<span id="cb11-91"><a href="#cb11-91" aria-hidden="true"></a></span>
<span id="cb11-92"><a href="#cb11-92" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Current version: </span><span class="va">$CURRENT_VERSION</span><span class="st">"</span></span>
<span id="cb11-93"><a href="#cb11-93" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Latest version: </span><span class="va">${LATEST_VERSION:-$CURRENT_VERSION}</span><span class="st">"</span></span>
<span id="cb11-94"><a href="#cb11-94" aria-hidden="true"></a></span>
<span id="cb11-95"><a href="#cb11-95" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$LATEST_VERSION</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-96"><a href="#cb11-96" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ PASS: WordPress is up to date"</span></span>
<span id="cb11-97"><a href="#cb11-97" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-98"><a href="#cb11-98" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"⚠ WARNING: WordPress update available"</span></span>
<span id="cb11-99"><a href="#cb11-99" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-100"><a href="#cb11-100" aria-hidden="true"></a></span>
<span id="cb11-101"><a href="#cb11-101" aria-hidden="true"></a><span class="kw">}</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb11-102"><a href="#cb11-102" aria-hidden="true"></a></span>
<span id="cb11-103"><a href="#cb11-103" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Security report generated: </span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb11-104"><a href="#cb11-104" aria-hidden="true"></a></span>
<span id="cb11-105"><a href="#cb11-105" aria-hidden="true"></a><span class="co"># Email report</span></span>
<span id="cb11-106"><a href="#cb11-106" aria-hidden="true"></a><span class="ex">mail</span> -s <span class="st">"WordPress Security Report - </span><span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span><span class="st">"</span> admin@example.com <span class="op">&lt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb11-107"><a href="#cb11-107" aria-hidden="true"></a></span>
<span id="cb11-108"><a href="#cb11-108" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Security report complete: </span><span class="va">$REPORT_FILE</span><span class="st">"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="automated-scheduling">Automated Scheduling</h3>



<p>Run security scans automatically with cron.</p>



<h4 class="wp-block-heading" id="cron-configuration">Cron Configuration</h4>



<div class="sourceCode" id="cb12">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a><span class="co"># Add to crontab: crontab -e</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a><span class="co"># Daily core integrity check at 2 AM</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a><span class="ex">0</span> 2 * * * /usr/local/bin/verify-core-integrity.sh <span class="op">&gt;&gt;</span> /var/log/wp-security.log <span class="op">2&gt;&amp;1</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true"></a><span class="co"># Daily vulnerability scan at 3 AM</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a><span class="ex">0</span> 3 * * * /usr/local/bin/scan-vulnerabilities.sh <span class="op">&gt;&gt;</span> /var/log/wp-security.log <span class="op">2&gt;&amp;1</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true"></a></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true"></a><span class="co"># Daily file change detection at 4 AM</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true"></a><span class="ex">0</span> 4 * * * /usr/local/bin/detect-file-changes.sh <span class="op">&gt;&gt;</span> /var/log/wp-security.log <span class="op">2&gt;&amp;1</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true"></a></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true"></a><span class="co"># Weekly comprehensive security report (Mondays at 8 AM)</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true"></a><span class="ex">0</span> 8 * * 1 /usr/local/bin/comprehensive-security-check.sh</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true"></a></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true"></a><span class="co"># Monthly user audit (first day of month)</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true"></a><span class="ex">0</span> 9 1 * * /usr/local/bin/audit-users.sh <span class="kw">|</span> <span class="ex">mail</span> -s <span class="st">"Monthly User Audit"</span> admin@example.com</span></code></pre>
</div>



<p>Learn about <a href="https://www.wordfence.com/learn/wordpress-security-best-practices/">WordPress security monitoring</a>.</p>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have automated WordPress security scanning and monitoring capabilities with WP-CLI.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: Core security</p>



<ul class="wp-block-list">
<li>Implement core integrity checks</li>



<li>Set up vulnerability scanning</li>



<li>Test alerting systems</li>
</ul>



<p><strong>Week 2</strong>: File monitoring</p>



<ul class="wp-block-list">
<li>Create file baselines</li>



<li>Configure change detection</li>



<li>Add malware scanning</li>
</ul>



<p><strong>Week 3</strong>: User security</p>



<ul class="wp-block-list">
<li>Audit user accounts</li>



<li>Check permissions</li>



<li>Implement password policies</li>
</ul>



<p><strong>Week 4</strong>: Automation</p>



<ul class="wp-block-list">
<li>Schedule all security checks</li>



<li>Configure comprehensive reports</li>



<li>Integrate with monitoring tools</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Intrusion Detection Systems</a></strong> &#8211; Advanced threat detection</li>



<li><strong><a href="#">Security Information and Event Management (SIEM)</a></strong> &#8211; Centralized security monitoring</li>



<li><strong><a href="#">Automated Incident Response</a></strong> &#8211; Automatic threat mitigation</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download security scripts</a></strong> including:</p>



<ul class="wp-block-list">
<li>Complete scanning system</li>



<li>Monitoring tools</li>



<li>Report templates</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>Security best practices</li>



<li>Threat response strategies</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>Automated WordPress security scanning with WP-CLI provides continuous protection against vulnerabilities, malware, and unauthorized changes—detecting threats before they compromise your sites.</p>



<p>What we covered:</p>



<p>✅ Core file integrity verification <br>✅ Plugin and theme vulnerability detection <br>✅ File change monitoring and alerting <br>✅ Malware pattern scanning <br>✅ User account security auditing <br>✅ Comprehensive automated security reports</p>



<p>Implement these security automation systems, and you’ll detect threats immediately—protecting WordPress sites 24/7 without constant manual monitoring.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">incident response</a> or <a href="#">WordPress hardening</a>.</p>



<p><strong>Questions about WordPress security automation?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other WordPress administrators.</p>
<p>The post <a href="https://wpclimastery.com/blog/automate-wordpress-security-scanning-and-monitoring-with-wp-cli/">Automate WordPress Security Scanning and Monitoring with WP-CLI</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Build a WordPress Deployment Pipeline with WP-CLI and Bash</title>
		<link>https://wpclimastery.com/blog/build-a-wordpress-deployment-pipeline-with-wp-cli-and-bash/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Tue, 10 Feb 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[WordPress Automation]]></category>
		<category><![CDATA[automated wordpress deployment]]></category>
		<category><![CDATA[deployment pipeline]]></category>
		<category><![CDATA[wordpress deployment]]></category>
		<category><![CDATA[wordpress devops]]></category>
		<category><![CDATA[wp-cli deployment]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=164</guid>

					<description><![CDATA[<p>Deploying WordPress changes manually means FTPing files, manually importing databases, running SQL updates, and crossing your fingers that nothing breaks. One mistake during deployment takes your production site offline during...</p>
<p>The post <a href="https://wpclimastery.com/blog/build-a-wordpress-deployment-pipeline-with-wp-cli-and-bash/">Build a WordPress Deployment Pipeline with WP-CLI and Bash</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Deploying WordPress changes manually means FTPing files, manually importing databases, running SQL updates, and crossing your fingers that nothing breaks. One mistake during deployment takes your production site offline during peak traffic hours.</p>



<p>A WordPress deployment pipeline automates the entire process—code changes flow from development through testing to production automatically, with safety checks, automated testing, rollback capability, and zero downtime. Deploy confidently dozens of times per day.</p>



<p>In this guide, you’ll build a complete WordPress deployment pipeline using WP-CLI and Bash, from basic scripts to production-ready systems used by professional WordPress development teams.</p>



<h3 class="wp-block-heading" id="why-pipeline">Why Build a Deployment Pipeline?</h3>



<p><a href="https://wordpress.org/support/article/updating-wordpress/">Manual WordPress deployments</a> don’t scale and introduce human error at every step.</p>



<h4 class="wp-block-heading" id="problems-with-manual-deployment">Problems with Manual Deployment</h4>



<p><strong>Error-prone</strong>: Manual file transfers and database updates cause mistakes.</p>



<p><strong>Downtime</strong>: Sites go offline during deployments affecting users and revenue.</p>



<p><strong>No testing</strong>: Changes deploy directly to production without validation.</p>



<p><strong>Slow</strong>: Manual deployments take 30-60 minutes of focused work.</p>



<p><strong>No rollback</strong>: Fixing failed deployments requires manual restoration from backups.</p>



<h4 class="wp-block-heading" id="deployment-pipeline-benefits">Deployment Pipeline Benefits</h4>



<p><strong>Automated</strong>: One command deploys entire release from development to production.</p>



<p><strong>Zero downtime</strong>: Users never see maintenance pages or errors.</p>



<p><strong>Tested</strong>: Automated tests catch issues before they reach production.</p>



<p><strong>Fast</strong>: Complete deployments in under 5 minutes instead of hours.</p>



<p><strong>Reversible</strong>: Instant rollback to previous version if issues occur.</p>



<p>According to <a href="https://cloud.google.com/devops/state-of-devops">DevOps Research</a>, teams with deployment pipelines deploy 200x more frequently with 24x faster recovery times.</p>



<h3 class="wp-block-heading" id="pipeline-components">Deployment Pipeline Components</h3>



<p>Understand the stages of a WordPress deployment pipeline.</p>



<h4 class="wp-block-heading" id="basic-pipeline-stages">Basic Pipeline Stages</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="ex">1.</span> Development  → Code changes made locally</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="ex">2.</span> Testing      → Automated tests verify changes</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a><span class="ex">3.</span> Staging      → Deploy to staging environment</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a><span class="ex">4.</span> Validation   → Manual/automated verification</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a><span class="ex">5.</span> Production   → Deploy to live site</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a><span class="ex">6.</span> Monitoring   → Track deployment health</span></code></pre>
</div>



<h4 class="wp-block-heading" id="essential-pipeline-elements">Essential Pipeline Elements</h4>



<p><strong>Version Control</strong>: Git tracks all changes and enables rollback.</p>



<p><strong>Database Migrations</strong>: Automated schema and data updates.</p>



<p><strong>Asset Building</strong>: Compile CSS, minify JavaScript, optimize images.</p>



<p><strong>Environment Config</strong>: Different settings for dev/staging/production.</p>



<p><strong>Health Checks</strong>: Verify deployment succeeded before completing.</p>



<p><strong>Rollback Strategy</strong>: Quick recovery from failed deployments.</p>



<p>Learn about <a href="https://www.atlassian.com/continuous-delivery/continuous-deployment">continuous deployment</a> principles.</p>



<h3 class="wp-block-heading" id="basic-deployment">Basic Deployment Script</h3>



<p>Start with a simple automated deployment workflow.</p>



<h4 class="wp-block-heading" id="manual-deployment-process">Manual Deployment Process</h4>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a><span class="co"># deploy-wordpress.sh - Basic deployment script</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a><span class="va">REPO_URL=</span><span class="st">"git@github.com:yourcompany/wordpress-site.git"</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a><span class="va">DEPLOY_PATH=</span><span class="st">"/var/www/production"</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a><span class="va">BRANCH=</span><span class="st">"main"</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Starting deployment..."</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true"></a><span class="co"># Pull latest code</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true"></a><span class="fu">git</span> fetch origin</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true"></a><span class="fu">git</span> reset --hard <span class="st">"origin/</span><span class="va">$BRANCH</span><span class="st">"</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true"></a></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true"></a><span class="co"># Install/update dependencies</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true"></a><span class="ex">composer</span> install --no-dev --optimize-autoloader</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true"></a></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true"></a><span class="co"># Run database migrations</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true"></a><span class="ex">wp</span> db migrate</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true"></a></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true"></a></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true"></a><span class="co"># Build assets (if needed)</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true"></a><span class="ex">npm</span> run build</span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true"></a></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Deployment complete"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="deployment-with-backup">Deployment with Backup</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># deploy-with-backup.sh</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="va">DEPLOY_PATH=</span><span class="st">"/var/www/production"</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="va">BACKUP_DIR=</span><span class="st">"/backups/deployments"</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a><span class="va">DATE=$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a><span class="co"># Create pre-deployment backup</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Creating backup..."</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">"</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/db-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a><span class="fu">git</span> rev-parse HEAD <span class="op">&gt;</span> <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/git-commit-</span><span class="va">$DATE</span><span class="st">.txt"</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a><span class="co"># Deploy</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Deploying..."</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a><span class="fu">git</span> pull origin main</span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a><span class="ex">composer</span> install --no-dev</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a><span class="co"># Database updates</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true"></a><span class="ex">wp</span> db migrate <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Migration failed, rolling back..."</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a>    <span class="ex">wp</span> db import <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/db-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a>    <span class="fu">git</span> reset --hard <span class="va">$(</span><span class="fu">cat</span> <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/git-commit-</span><span class="va">$DATE</span><span class="st">.txt"</span><span class="va">)</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true"></a></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true"></a></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Deployment complete"</span></span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backup: </span><span class="va">$BACKUP_DIR</span><span class="st">/db-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="staging-to-production">Staging to Production Pipeline</h3>



<p>Deploy changes from staging environment to production safely.</p>



<h4 class="wp-block-heading" id="complete-staging-deploy">Complete Staging Deploy</h4>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="co"># deploy-staging-to-production.sh</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a><span class="va">STAGING_PATH=</span><span class="st">"/var/www/staging"</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a><span class="va">PROD_PATH=</span><span class="st">"/var/www/production"</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a><span class="va">BACKUP_DIR=</span><span class="st">"/backups/production"</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a><span class="va">DATE=$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=== Staging to Production Deployment ==="</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a><span class="co"># Step 1: Backup production</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 1/6: Backing up production..."</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$PROD_PATH</span><span class="st">"</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true"></a></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/db-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true"></a><span class="fu">tar</span> -czf <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/files-</span><span class="va">$DATE</span><span class="st">.tar.gz"</span> <span class="kw">\</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true"></a>    <span class="ex">wp-content/plugins</span> <span class="kw">\</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a>    <span class="ex">wp-content/themes</span> <span class="kw">\</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true"></a>    <span class="ex">wp-content/uploads</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true"></a></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Backup complete"</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true"></a></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true"></a><span class="co"># Step 2: Get staging code version</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 2/6: Getting staging version..."</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$STAGING_PATH</span><span class="st">"</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true"></a><span class="va">STAGING_COMMIT=$(</span><span class="fu">git</span> rev-parse HEAD<span class="va">)</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Staging commit: </span><span class="va">$STAGING_COMMIT</span><span class="st">"</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true"></a></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true"></a><span class="co"># Step 3: Deploy code to production</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 3/6: Deploying code..."</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$PROD_PATH</span><span class="st">"</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true"></a></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true"></a><span class="co"># Enable maintenance mode</span></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true"></a><span class="ex">wp</span> maintenance-mode activate</span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true"></a></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true"></a><span class="fu">git</span> fetch origin</span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true"></a><span class="fu">git</span> reset --hard <span class="st">"</span><span class="va">$STAGING_COMMIT</span><span class="st">"</span></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true"></a></span>
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true"></a><span class="co"># Step 4: Install dependencies</span></span>
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 4/6: Installing dependencies..."</span></span>
<span id="cb4-43"><a href="#cb4-43" aria-hidden="true"></a><span class="ex">composer</span> install --no-dev --no-interaction</span>
<span id="cb4-44"><a href="#cb4-44" aria-hidden="true"></a></span>
<span id="cb4-45"><a href="#cb4-45" aria-hidden="true"></a><span class="co"># Build assets</span></span>
<span id="cb4-46"><a href="#cb4-46" aria-hidden="true"></a><span class="ex">npm</span> run build</span>
<span id="cb4-47"><a href="#cb4-47" aria-hidden="true"></a></span>
<span id="cb4-48"><a href="#cb4-48" aria-hidden="true"></a><span class="co"># Step 5: Run database migrations</span></span>
<span id="cb4-49"><a href="#cb4-49" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 5/6: Running database migrations..."</span></span>
<span id="cb4-50"><a href="#cb4-50" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> db migrate<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb4-51"><a href="#cb4-51" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Migration failed, rolling back..."</span></span>
<span id="cb4-52"><a href="#cb4-52" aria-hidden="true"></a>    <span class="ex">wp</span> db import <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/db-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span>
<span id="cb4-53"><a href="#cb4-53" aria-hidden="true"></a>    <span class="ex">wp</span> maintenance-mode deactivate</span>
<span id="cb4-54"><a href="#cb4-54" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb4-55"><a href="#cb4-55" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-56"><a href="#cb4-56" aria-hidden="true"></a></span>
<span id="cb4-57"><a href="#cb4-57" aria-hidden="true"></a><span class="co"># Step 6: Final checks and cleanup</span></span>
<span id="cb4-58"><a href="#cb4-58" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 6/6: Final checks..."</span></span>
<span id="cb4-59"><a href="#cb4-59" aria-hidden="true"></a></span>
<span id="cb4-60"><a href="#cb4-60" aria-hidden="true"></a><span class="co"># Verify WordPress works</span></span>
<span id="cb4-61"><a href="#cb4-61" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> core is-installed<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb4-62"><a href="#cb4-62" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ WordPress check failed, rolling back..."</span></span>
<span id="cb4-63"><a href="#cb4-63" aria-hidden="true"></a>    <span class="ex">wp</span> db import <span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/db-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span>
<span id="cb4-64"><a href="#cb4-64" aria-hidden="true"></a>    <span class="ex">wp</span> maintenance-mode deactivate</span>
<span id="cb4-65"><a href="#cb4-65" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb4-66"><a href="#cb4-66" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-67"><a href="#cb4-67" aria-hidden="true"></a></span>
<span id="cb4-68"><a href="#cb4-68" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb4-69"><a href="#cb4-69" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb4-70"><a href="#cb4-70" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb4-71"><a href="#cb4-71" aria-hidden="true"></a></span>
<span id="cb4-72"><a href="#cb4-72" aria-hidden="true"></a><span class="co"># Disable maintenance mode</span></span>
<span id="cb4-73"><a href="#cb4-73" aria-hidden="true"></a><span class="ex">wp</span> maintenance-mode deactivate</span>
<span id="cb4-74"><a href="#cb4-74" aria-hidden="true"></a></span>
<span id="cb4-75"><a href="#cb4-75" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=== Deployment Complete ==="</span></span>
<span id="cb4-76"><a href="#cb4-76" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Deployed commit: </span><span class="va">$STAGING_COMMIT</span><span class="st">"</span></span>
<span id="cb4-77"><a href="#cb4-77" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backup: </span><span class="va">$BACKUP_DIR</span><span class="st">/db-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="automated-validation">Automated Validation</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="co"># validate-deployment.sh</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">SITE_URL=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Validating deployment..."</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a><span class="co"># Test homepage</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a><span class="va">HTTP_CODE=$(</span><span class="ex">curl</span> -s -o /dev/null -w <span class="st">"%{http_code}"</span> <span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$HTTP_CODE</span><span class="st">"</span> <span class="ot">!=</span> <span class="st">"200"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Homepage failed: HTTP </span><span class="va">$HTTP_CODE</span><span class="st">"</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Homepage accessible"</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a><span class="co"># Test admin</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a><span class="va">ADMIN_CODE=$(</span><span class="ex">curl</span> -s -o /dev/null -w <span class="st">"%{http_code}"</span> <span class="st">"</span><span class="va">$SITE_URL</span><span class="st">/wp-admin/"</span><span class="va">)</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$ADMIN_CODE</span><span class="st">"</span> <span class="ot">!=</span> <span class="st">"200"</span><span class="bu"> ]</span> <span class="kw">&amp;&amp;</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$ADMIN_CODE</span><span class="st">"</span> <span class="ot">!=</span> <span class="st">"302"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Admin failed: HTTP </span><span class="va">$ADMIN_CODE</span><span class="st">"</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Admin accessible"</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true"></a></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true"></a><span class="co"># Test critical pages</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">PAGE</span> in <span class="st">"/about"</span> <span class="st">"/contact"</span> <span class="st">"/shop"</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true"></a>    <span class="va">CODE=$(</span><span class="ex">curl</span> -s -o /dev/null -w <span class="st">"%{http_code}"</span> <span class="st">"</span><span class="va">$SITE_URL$PAGE</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$CODE</span><span class="st">"</span> <span class="ot">=</span> <span class="st">"200"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ </span><span class="va">$PAGE</span><span class="st"> accessible"</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"⚠ </span><span class="va">$PAGE</span><span class="st"> returned HTTP </span><span class="va">$CODE</span><span class="st">"</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true"></a></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Validation complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="zero-downtime">Zero-Downtime Deployment</h3>



<p>Deploy without taking the site offline.</p>



<h4 class="wp-block-heading" id="symlink-strategy">Symlink Strategy</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="co"># zero-downtime-deploy.sh</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a><span class="va">DEPLOY_BASE=</span><span class="st">"/var/www/releases"</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="va">CURRENT_LINK=</span><span class="st">"/var/www/current"</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a><span class="va">SHARED_DIR=</span><span class="st">"/var/www/shared"</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a><span class="va">RELEASE_ID=$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a><span class="va">RELEASE_PATH=</span><span class="st">"</span><span class="va">$DEPLOY_BASE</span><span class="st">/</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=== Zero-Downtime Deployment ==="</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Release ID: </span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a><span class="co"># Create new release directory</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true"></a><span class="co"># Clone code</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true"></a><span class="fu">git</span> clone --depth 1 git@github.com:yourcompany/site.git .</span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true"></a></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true"></a><span class="co"># Link shared directories</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true"></a><span class="fu">ln</span> -s <span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">/wp-content/uploads"</span> wp-content/uploads</span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true"></a><span class="fu">ln</span> -s <span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">/wp-config.php"</span> wp-config.php</span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true"></a></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true"></a><span class="co"># Install dependencies</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true"></a><span class="ex">composer</span> install --no-dev</span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true"></a></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true"></a><span class="co"># Build assets</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true"></a><span class="ex">npm</span> run build</span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true"></a></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true"></a><span class="co"># Database migrations (on shared database)</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">"</span></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true"></a><span class="ex">wp</span> db migrate --path=<span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true"></a></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true"></a><span class="co"># Atomic switch to new release</span></span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true"></a><span class="fu">ln</span> -sfn <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true"></a></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true"></a><span class="co"># Webserver points to /var/www/current</span></span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true"></a></span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true"></a><span class="co"># Cleanup old releases (keep last 5)</span></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEPLOY_BASE</span><span class="st">"</span></span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true"></a><span class="fu">ls</span> -t <span class="kw">|</span> <span class="fu">tail</span> -n +6 <span class="kw">|</span> <span class="fu">xargs</span> rm -rf</span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true"></a></span>
<span id="cb6-45"><a href="#cb6-45" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Deployment complete"</span></span>
<span id="cb6-46"><a href="#cb6-46" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Current release: </span><span class="va">$RELEASE_ID</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="blue-green-deployment">Blue-Green Deployment</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="co"># blue-green-deploy.sh</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a><span class="va">BLUE_PATH=</span><span class="st">"/var/www/blue"</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="va">GREEN_PATH=</span><span class="st">"/var/www/green"</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a><span class="va">CURRENT_LINK=</span><span class="st">"/var/www/current"</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a><span class="co"># Determine inactive environment</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$(</span><span class="fu">readlink</span> <span class="va">$CURRENT_LINK)</span><span class="st">"</span> <span class="ot">=</span> <span class="st">"</span><span class="va">$BLUE_PATH</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a>    <span class="va">INACTIVE=</span><span class="st">"</span><span class="va">$GREEN_PATH</span><span class="st">"</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a>    <span class="va">INACTIVE_NAME=</span><span class="st">"green"</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a>    <span class="va">INACTIVE=</span><span class="st">"</span><span class="va">$BLUE_PATH</span><span class="st">"</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a>    <span class="va">INACTIVE_NAME=</span><span class="st">"blue"</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Deploying to inactive environment: </span><span class="va">$INACTIVE_NAME</span><span class="st">"</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$INACTIVE</span><span class="st">"</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a><span class="co"># Deploy to inactive</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a><span class="fu">git</span> pull origin main</span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a><span class="ex">composer</span> install --no-dev</span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a><span class="ex">npm</span> run build</span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true"></a></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true"></a><span class="co"># Test inactive environment</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">curl</span> -f <span class="st">"http://localhost:8080"</span> <span class="op">&gt;</span> /dev/null <span class="op">2&gt;&amp;1</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ Inactive environment healthy"</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Inactive environment failed health check"</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true"></a></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true"></a><span class="co"># Switch traffic to new version</span></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true"></a><span class="fu">ln</span> -sfn <span class="st">"</span><span class="va">$INACTIVE</span><span class="st">"</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true"></a></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true"></a><span class="co"># Reload webserver</span></span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true"></a><span class="ex">systemctl</span> reload nginx</span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true"></a></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Switched to </span><span class="va">$INACTIVE_NAME</span><span class="st"> environment"</span></span></code></pre>
</div>



<p>Learn about <a href="https://docs.aws.amazon.com/whitepapers/latest/blue-green-deployments/welcome.html">zero-downtime deployment strategies</a>.</p>



<h3 class="wp-block-heading" id="database-migrations">Database Migration Handling</h3>



<p>Safely manage database schema changes during deployments.</p>



<h4 class="wp-block-heading" id="migration-system">Migration System</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="co"># db-migrate.sh - Run database migrations</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a><span class="va">MIGRATIONS_DIR=</span><span class="st">"/var/www/db/migrations"</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a><span class="va">APPLIED_FILE=</span><span class="st">"/var/www/db/applied-migrations.txt"</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a><span class="fu">touch</span> <span class="st">"</span><span class="va">$APPLIED_FILE</span><span class="st">"</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Running database migrations..."</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">MIGRATION</span> in <span class="va">$(</span><span class="fu">ls</span> <span class="st">"</span><span class="va">$MIGRATIONS_DIR</span><span class="st">"</span>/*.sql <span class="kw">|</span> <span class="fu">sort</span><span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true"></a>    <span class="va">MIGRATION_NAME=$(</span><span class="fu">basename</span> <span class="st">"</span><span class="va">$MIGRATION</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a>    <span class="co"># Check if already applied</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a>    <span class="kw">if</span> <span class="fu">grep</span> -q <span class="st">"</span><span class="va">$MIGRATION_NAME</span><span class="st">"</span> <span class="st">"</span><span class="va">$APPLIED_FILE</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"⊘ Skipping: </span><span class="va">$MIGRATION_NAME</span><span class="st"> (already applied)"</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true"></a>        <span class="bu">continue</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Applying: </span><span class="va">$MIGRATION_NAME</span><span class="st">"</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a>    <span class="co"># Run migration</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> db query <span class="op">&lt;</span> <span class="st">"</span><span class="va">$MIGRATION</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"</span><span class="va">$MIGRATION_NAME</span><span class="st">"</span> <span class="op">&gt;&gt;</span> <span class="st">"</span><span class="va">$APPLIED_FILE</span><span class="st">"</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✓ Applied: </span><span class="va">$MIGRATION_NAME</span><span class="st">"</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"✗ Failed: </span><span class="va">$MIGRATION_NAME</span><span class="st">"</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true"></a>        <span class="bu">exit</span> 1</span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true"></a></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ All migrations applied"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="reversible-migrations">Reversible Migrations</h4>



<div class="sourceCode" id="cb9">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co"># Migration file structure</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a><span class="co"># migrations/001-add-custom-table.sql (up)</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a><span class="co"># migrations/001-add-custom-table-rollback.sql (down)</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a><span class="co"># rollback-migration.sh</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a><span class="va">MIGRATION_ID=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a><span class="va">MIGRATIONS_DIR=</span><span class="st">"/var/www/db/migrations"</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a><span class="va">ROLLBACK_FILE=</span><span class="st">"</span><span class="va">$MIGRATIONS_DIR</span><span class="st">/</span><span class="va">${MIGRATION_ID}</span><span class="st">-rollback.sql"</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$ROLLBACK_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Rollback file not found: </span><span class="va">$ROLLBACK_FILE</span><span class="st">"</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true"></a></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Rolling back migration: </span><span class="va">$MIGRATION_ID</span><span class="st">"</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true"></a><span class="ex">wp</span> db query <span class="op">&lt;</span> <span class="st">"</span><span class="va">$ROLLBACK_FILE</span><span class="st">"</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true"></a></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Rollback complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="notifications">Deployment Notifications</h3>



<p>Alert teams about deployment status.</p>



<h4 class="wp-block-heading" id="slack-notifications">Slack Notifications</h4>



<div class="sourceCode" id="cb10">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a><span class="co"># notify-deployment.sh</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a><span class="va">SLACK_WEBHOOK=</span><span class="st">"https://hooks.slack.com/services/YOUR/WEBHOOK/URL"</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a><span class="va">STATUS=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span>  # <span class="ex">success</span> or failure</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a><span class="va">COMMIT=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a><span class="va">DEPLOYER=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$STATUS</span><span class="st">"</span> <span class="ot">=</span> <span class="st">"success"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a>    <span class="va">COLOR=</span><span class="st">"good"</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a>    <span class="va">MESSAGE=</span><span class="st">"Deployment successful"</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></a>    <span class="va">COLOR=</span><span class="st">"danger"</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true"></a>    <span class="va">MESSAGE=</span><span class="st">"Deployment failed"</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true"></a></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true"></a><span class="ex">curl</span> -X POST <span class="st">"</span><span class="va">$SLACK_WEBHOOK</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true"></a>    <span class="ex">-H</span> <span class="st">'Content-Type: application/json'</span> <span class="kw">\</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true"></a>    <span class="ex">-d</span> <span class="st">"{</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true"></a><span class="st">        </span><span class="dt">\"</span><span class="st">attachments</span><span class="dt">\"</span><span class="st">: [{</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true"></a><span class="st">            </span><span class="dt">\"</span><span class="st">color</span><span class="dt">\"</span><span class="st">: </span><span class="dt">\"</span><span class="va">$COLOR</span><span class="dt">\"</span><span class="st">,</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true"></a><span class="st">            </span><span class="dt">\"</span><span class="st">title</span><span class="dt">\"</span><span class="st">: </span><span class="dt">\"</span><span class="va">$MESSAGE</span><span class="dt">\"</span><span class="st">,</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true"></a><span class="st">            </span><span class="dt">\"</span><span class="st">fields</span><span class="dt">\"</span><span class="st">: [</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true"></a><span class="st">                {</span><span class="dt">\"</span><span class="st">title</span><span class="dt">\"</span><span class="st">: </span><span class="dt">\"</span><span class="st">Environment</span><span class="dt">\"</span><span class="st">, </span><span class="dt">\"</span><span class="st">value</span><span class="dt">\"</span><span class="st">: </span><span class="dt">\"</span><span class="st">Production</span><span class="dt">\"</span><span class="st">, </span><span class="dt">\"</span><span class="st">short</span><span class="dt">\"</span><span class="st">: true},</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true"></a><span class="st">                {</span><span class="dt">\"</span><span class="st">title</span><span class="dt">\"</span><span class="st">: </span><span class="dt">\"</span><span class="st">Commit</span><span class="dt">\"</span><span class="st">, </span><span class="dt">\"</span><span class="st">value</span><span class="dt">\"</span><span class="st">: </span><span class="dt">\"</span><span class="va">$COMMIT</span><span class="dt">\"</span><span class="st">, </span><span class="dt">\"</span><span class="st">short</span><span class="dt">\"</span><span class="st">: true},</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true"></a><span class="st">                {</span><span class="dt">\"</span><span class="st">title</span><span class="dt">\"</span><span class="st">: </span><span class="dt">\"</span><span class="st">Deployed by</span><span class="dt">\"</span><span class="st">, </span><span class="dt">\"</span><span class="st">value</span><span class="dt">\"</span><span class="st">: </span><span class="dt">\"</span><span class="va">$DEPLOYER</span><span class="dt">\"</span><span class="st">, </span><span class="dt">\"</span><span class="st">short</span><span class="dt">\"</span><span class="st">: true}</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true"></a><span class="st">            ]</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true"></a><span class="st">        }]</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true"></a><span class="st">    }"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="email-notifications">Email Notifications</h4>



<div class="sourceCode" id="cb11">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="co"># email-deployment-report.sh</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a><span class="va">EMAIL=</span><span class="st">"team@example.com"</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a><span class="va">STATUS=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a><span class="va">DETAILS=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a><span class="va">SUBJECT=</span><span class="st">"WordPress Deployment </span><span class="va">$STATUS</span><span class="st">"</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true"></a><span class="fu">cat</span> <span class="op">&lt;&lt;EOF</span> <span class="kw">|</span> <span class="ex">mail</span> -s <span class="st">"</span><span class="va">$SUBJECT</span><span class="st">"</span> <span class="st">"</span><span class="va">$EMAIL</span><span class="st">"</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true"></a>WordPress Deployment Report</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true"></a>===========================</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true"></a></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true"></a>Status: <span class="va">$STATUS</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true"></a>Time: <span class="va">$(</span><span class="fu">date</span><span class="va">)</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true"></a>Server: <span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true"></a>Deployed by: <span class="va">$(</span><span class="fu">whoami</span><span class="va">)</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true"></a></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true"></a>Details:</span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true"></a><span class="va">$DETAILS</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true"></a></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true"></a>Automated deployment system</span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true"></a>EOF</span></code></pre>
</div>



<h3 class="wp-block-heading" id="complete-pipeline">Complete Production Pipeline</h3>



<p>Integrate all components into a complete system.</p>



<h4 class="wp-block-heading" id="master-deployment-script">Master Deployment Script</h4>



<div class="sourceCode" id="cb12">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a><span class="co"># deploy.sh - Complete deployment pipeline</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>staging<span class="va">}</span><span class="st">"</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"/var/log/deployments/deploy-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d-%H%M%S<span class="va">)</span><span class="st">.log"</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true"></a></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="va">$LOG_FILE)</span><span class="st">"</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true"></a></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true"></a></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true"></a><span class="fu">notify()</span> <span class="kw">{</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true"></a>    <span class="ex">./notify-deployment.sh</span> <span class="st">"</span><span class="va">$1</span><span class="st">"</span> <span class="st">"</span><span class="va">$2</span><span class="st">"</span> <span class="st">"</span><span class="va">$(</span><span class="fu">whoami</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true"></a></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Deployment Started ==="</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Environment: </span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true"></a></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true"></a><span class="co"># Pre-deployment checks</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running pre-deployment checks..."</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true"></a><span class="ex">./pre-deploy-check.sh</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✗ Pre-deployment checks failed"</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true"></a>    <span class="ex">notify</span> <span class="st">"failure"</span> <span class="st">"Pre-deployment checks failed"</span></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true"></a></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true"></a><span class="co"># Backup</span></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating backup..."</span></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true"></a><span class="ex">./backup.sh</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true"></a></span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true"></a><span class="co"># Deploy code</span></span>
<span id="cb12-35"><a href="#cb12-35" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Deploying code..."</span></span>
<span id="cb12-36"><a href="#cb12-36" aria-hidden="true"></a><span class="ex">./deploy-code.sh</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb12-37"><a href="#cb12-37" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✗ Code deployment failed"</span></span>
<span id="cb12-38"><a href="#cb12-38" aria-hidden="true"></a>    <span class="ex">./rollback.sh</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb12-39"><a href="#cb12-39" aria-hidden="true"></a>    <span class="ex">notify</span> <span class="st">"failure"</span> <span class="st">"Code deployment failed"</span></span>
<span id="cb12-40"><a href="#cb12-40" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-41"><a href="#cb12-41" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb12-42"><a href="#cb12-42" aria-hidden="true"></a></span>
<span id="cb12-43"><a href="#cb12-43" aria-hidden="true"></a><span class="co"># Database migrations</span></span>
<span id="cb12-44"><a href="#cb12-44" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running database migrations..."</span></span>
<span id="cb12-45"><a href="#cb12-45" aria-hidden="true"></a><span class="ex">./db-migrate.sh</span> <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb12-46"><a href="#cb12-46" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✗ Database migration failed"</span></span>
<span id="cb12-47"><a href="#cb12-47" aria-hidden="true"></a>    <span class="ex">./rollback.sh</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb12-48"><a href="#cb12-48" aria-hidden="true"></a>    <span class="ex">notify</span> <span class="st">"failure"</span> <span class="st">"Database migration failed"</span></span>
<span id="cb12-49"><a href="#cb12-49" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-50"><a href="#cb12-50" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb12-51"><a href="#cb12-51" aria-hidden="true"></a></span>
<span id="cb12-52"><a href="#cb12-52" aria-hidden="true"></a><span class="co"># Post-deployment validation</span></span>
<span id="cb12-53"><a href="#cb12-53" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Validating deployment..."</span></span>
<span id="cb12-54"><a href="#cb12-54" aria-hidden="true"></a><span class="ex">./validate-deployment.sh</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb12-55"><a href="#cb12-55" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✗ Validation failed"</span></span>
<span id="cb12-56"><a href="#cb12-56" aria-hidden="true"></a>    <span class="ex">./rollback.sh</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb12-57"><a href="#cb12-57" aria-hidden="true"></a>    <span class="ex">notify</span> <span class="st">"failure"</span> <span class="st">"Deployment validation failed"</span></span>
<span id="cb12-58"><a href="#cb12-58" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-59"><a href="#cb12-59" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb12-60"><a href="#cb12-60" aria-hidden="true"></a></span>
<span id="cb12-61"><a href="#cb12-61" aria-hidden="true"></a><span class="co"># Success</span></span>
<span id="cb12-62"><a href="#cb12-62" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Deployment Complete ==="</span></span>
<span id="cb12-63"><a href="#cb12-63" aria-hidden="true"></a><span class="ex">notify</span> <span class="st">"success"</span> <span class="st">"Deployment to </span><span class="va">$ENVIRONMENT</span><span class="st"> successful"</span></span>
<span id="cb12-64"><a href="#cb12-64" aria-hidden="true"></a></span>
<span id="cb12-65"><a href="#cb12-65" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Deployment successful"</span></span>
<span id="cb12-66"><a href="#cb12-66" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Log: </span><span class="va">$LOG_FILE</span><span class="st">"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have a complete WordPress deployment pipeline built with WP-CLI and Bash.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: Basic automation</p>



<ul class="wp-block-list">
<li>Create simple deploy scripts</li>



<li>Add backup mechanisms</li>



<li>Implement rollback procedures</li>
</ul>



<p><strong>Week 2</strong>: Testing integration</p>



<ul class="wp-block-list">
<li>Add validation checks</li>



<li>Create health checks</li>



<li>Automate testing</li>
</ul>



<p><strong>Week 3</strong>: Zero-downtime</p>



<ul class="wp-block-list">
<li>Implement symlink strategy</li>



<li>Set up blue-green deployment</li>



<li>Test switching mechanisms</li>
</ul>



<p><strong>Week 4</strong>: Production hardening</p>



<ul class="wp-block-list">
<li>Add monitoring</li>



<li>Implement notifications</li>



<li>Document procedures</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Container Deployments</a></strong> &#8211; Docker-based pipelines</li>



<li><strong><a href="#">GitOps Workflows</a></strong> &#8211; Git-driven deployments</li>



<li><strong><a href="#">Multi-Region Deployment</a></strong> &#8211; Global site deployment</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download deployment scripts</a></strong> including:</p>



<ul class="wp-block-list">
<li>Complete pipeline system</li>



<li>Testing frameworks</li>



<li>Rollback automation</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>DevOps best practices</li>



<li>Deployment strategies</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>A WordPress deployment pipeline transforms risky manual deployments into reliable, automated workflows that enable rapid, confident releases to production.</p>



<p>What we covered:</p>



<p>✅ Deployment pipeline components and stages <br>✅ Basic deployment automation with backups <br>✅ Staging to production workflows <br>✅ Zero-downtime deployment strategies <br>✅ Database migration handling <br>✅ Complete production pipeline integration</p>



<p>Master these techniques, and you’ll deploy WordPress changes confidently dozens of times per day with zero downtime and instant rollback capability.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">continuous integration</a> or <a href="#">infrastructure as code</a>.</p>



<p><strong>Questions about WordPress deployment pipelines?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other WordPress DevOps teams.</p>
<p>The post <a href="https://wpclimastery.com/blog/build-a-wordpress-deployment-pipeline-with-wp-cli-and-bash/">Build a WordPress Deployment Pipeline with WP-CLI and Bash</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Bulk Content Operations in WordPress: WP-CLI Advanced Techniques</title>
		<link>https://wpclimastery.com/blog/bulk-content-operations-in-wordpress-wp-cli-advanced-techniques/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Thu, 05 Feb 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Content Management Automation]]></category>
		<category><![CDATA[batch content management]]></category>
		<category><![CDATA[bulk content wordpress]]></category>
		<category><![CDATA[wordpress mass edit]]></category>
		<category><![CDATA[wp-cli bulk operations]]></category>
		<category><![CDATA[wpcli content tools]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=141</guid>

					<description><![CDATA[<p>Managing hundreds or thousands of WordPress posts through the admin panel is impossible—updating categories across 500 posts, changing authors on old content, or adding custom fields to existing articles wastes...</p>
<p>The post <a href="https://wpclimastery.com/blog/bulk-content-operations-in-wordpress-wp-cli-advanced-techniques/">Bulk Content Operations in WordPress: WP-CLI Advanced Techniques</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Managing hundreds or thousands of WordPress posts through the admin panel is impossible—updating categories across 500 posts, changing authors on old content, or adding custom fields to existing articles wastes days of manual clicking.</p>



<p>WP-CLI transforms bulk content operations from tedious manual work into fast, scriptable workflows. Update unlimited posts with one command, batch-assign taxonomies, transform content structure, and automate complex content management tasks.</p>



<p>In this guide, you’ll learn advanced WP-CLI techniques for bulk content operations used by high-volume WordPress publishers managing thousands of posts efficiently.</p>



<h3 class="wp-block-heading" id="why-bulk-operations">Why Bulk Content Operations Matter</h3>



<p><a href="https://wordpress.org/support/article/posts-screen/">WordPress content management</a> at scale requires automation—manual operations don’t work beyond 50-100 posts.</p>



<h4 class="wp-block-heading" id="problems-with-manual-bulk-editing">Problems with Manual Bulk Editing</h4>



<p><strong>Time-consuming</strong>: Updating 1,000 posts manually takes weeks of repetitive work.</p>



<p><strong>Error-prone</strong>: Manual operations introduce inconsistencies and mistakes.</p>



<p><strong>Limited scope</strong>: Can’t perform complex transformations or conditional updates.</p>



<p><strong>No validation</strong>: Can’t preview changes before executing them.</p>



<p><strong>Not repeatable</strong>: Can’t reuse workflows or share processes with team.</p>



<h4 class="wp-block-heading" id="wp-cli-bulk-operation-advantages">WP-CLI Bulk Operation Advantages</h4>



<p><strong>Lightning fast</strong>: Update 10,000 posts in minutes instead of weeks.</p>



<p><strong>Scriptable</strong>: Save complex operations as reusable scripts.</p>



<p><strong>Conditional logic</strong>: Update only posts matching specific criteria.</p>



<p><strong>Preview mode</strong>: Test operations before executing on production data.</p>



<p><strong>Audit trails</strong>: Log all changes for compliance and debugging.</p>



<p>According to <a href="https://contentmarketinginstitute.com/">content management studies</a>, sites with 1,000+ posts save 40+ hours monthly with automated bulk operations.</p>



<h3 class="wp-block-heading" id="post-status">Bulk Post Status Operations</h3>



<p>Manage post publication status at scale.</p>



<h4 class="wp-block-heading" id="bulk-status-changes">Bulk Status Changes</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="co"># Publish all drafts</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="ex">wp</span> post update <span class="va">$(</span><span class="ex">wp</span> post list --post_status=draft --format=ids<span class="va">)</span> --post_status=publish</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a><span class="co"># Draft all scheduled posts</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a><span class="ex">wp</span> post update <span class="va">$(</span><span class="ex">wp</span> post list --post_status=future --format=ids<span class="va">)</span> --post_status=draft</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a><span class="co"># Unpublish posts older than 2 years</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a><span class="ex">wp</span> post list --post_status=publish --before=<span class="st">"2 years ago"</span> --format=ids <span class="kw">|</span> <span class="fu">xargs</span> wp post update --post_status=draft</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a><span class="co"># Archive old posts (change status)</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a><span class="va">YEAR_AGO=$(</span><span class="fu">date</span> -d <span class="st">"1 year ago"</span> +%Y-%m-%d<span class="va">)</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a><span class="ex">wp</span> post update <span class="va">$(</span><span class="ex">wp</span> post list --post_status=publish --before=<span class="st">"</span><span class="va">$YEAR_AGO</span><span class="st">"</span> --format=ids<span class="va">)</span> --post_status=private</span></code></pre>
</div>



<h4 class="wp-block-heading" id="conditional-status-updates">Conditional Status Updates</h4>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a><span class="co"># update-post-status-by-category.sh</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a><span class="va">CATEGORY_ID=</span>5  # <span class="ex">Posts</span> in this category</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a><span class="va">TARGET_STATUS=</span><span class="st">"draft"</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a><span class="co"># Get posts in specific category</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a><span class="va">POSTS=$(</span><span class="ex">wp</span> post list --category_id=<span class="va">$CATEGORY_ID</span> --post_status=publish --format=ids<span class="va">)</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$POSTS</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"No posts found in category </span><span class="va">$CATEGORY_ID</span><span class="st">"</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a>    <span class="bu">exit</span> 0</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true"></a></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true"></a><span class="co"># Count posts</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true"></a><span class="va">COUNT=$(</span><span class="bu">echo</span> <span class="va">$POSTS</span> <span class="kw">|</span> <span class="fu">wc</span> -w<span class="va">)</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Found </span><span class="va">$COUNT</span><span class="st"> posts to update"</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true"></a><span class="co"># Update status</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true"></a><span class="ex">wp</span> post update <span class="va">$POSTS</span> --post_status=<span class="va">$TARGET_STATUS</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true"></a></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Updated </span><span class="va">$COUNT</span><span class="st"> posts to </span><span class="va">$TARGET_STATUS</span><span class="st"> status"</span></span></code></pre>
</div>



<p>Learn more about <a href="https://wordpress.org/support/article/post-status/">WordPress post statuses</a>.</p>



<h3 class="wp-block-heading" id="taxonomy-operations">Bulk Taxonomy Assignment</h3>



<p>Assign categories, tags, and custom taxonomies in bulk.</p>



<h4 class="wp-block-heading" id="bulk-category-operations">Bulk Category Operations</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co"># Add category to all posts</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="va">CATEGORY_ID=</span>10</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a>    <span class="ex">wp</span> post term add <span class="va">$post_id</span> category <span class="va">$CATEGORY_ID</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="co"># Remove category from all posts</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a>    <span class="ex">wp</span> post term remove <span class="va">$post_id</span> category 3</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a><span class="co"># Replace category across posts</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a><span class="va">OLD_CAT=</span>5</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a><span class="va">NEW_CAT=</span>10</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a><span class="va">POSTS=$(</span><span class="ex">wp</span> post list --category=<span class="va">$OLD_CAT</span> --format=ids<span class="va">)</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$POSTS</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a>    <span class="ex">wp</span> post term remove <span class="va">$post_id</span> category <span class="va">$OLD_CAT</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a>    <span class="ex">wp</span> post term add <span class="va">$post_id</span> category <span class="va">$NEW_CAT</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Category replacement complete"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="bulk-tag-operations">Bulk Tag Operations</h4>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="co"># Add tags to all posts without tags</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="ex">wp</span> post list --format=ids <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">post_id</span>; <span class="kw">do</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a>    <span class="va">TAG_COUNT=$(</span><span class="ex">wp</span> post term list <span class="va">$post_id</span> post_tag --format=count<span class="va">)</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$TAG_COUNT</span><span class="st">"</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Adding tags to post </span><span class="va">$post_id</span><span class="st">"</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a>        <span class="ex">wp</span> post term add <span class="va">$post_id</span> post_tag <span class="st">"general,uncategorized"</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a><span class="co"># Remove all tags from specific category</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a><span class="va">POSTS=$(</span><span class="ex">wp</span> post list --category_name=<span class="st">"old-news"</span> --format=ids<span class="va">)</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$POSTS</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a>    <span class="ex">wp</span> post term remove <span class="va">$post_id</span> post_tag --all</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="smart-auto-categorization">Smart Auto-Categorization</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="co"># auto-categorize-by-keywords.sh - Assign categories based on content</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="co"># Define keyword-to-category mapping</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="bu">declare</span> -A <span class="va">KEYWORDS=(</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a>    [<span class="st">"WordPress"</span>]=<span class="st">"5"</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a>    [<span class="st">"security"</span>]=<span class="st">"8"</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a>    [<span class="st">"performance"</span>]=<span class="st">"12"</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a>    [<span class="st">"tutorial"</span>]=<span class="st">"15"</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a>)</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a><span class="co"># Search for keywords and assign categories</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">KEYWORD</span> in <span class="st">"</span><span class="va">${!KEYWORDS[@]}</span><span class="st">"</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a>    <span class="va">CAT_ID=</span><span class="st">"</span><span class="va">${KEYWORDS[$KEYWORD]}</span><span class="st">"</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Processing keyword: </span><span class="va">$KEYWORD</span><span class="st"> → Category </span><span class="va">$CAT_ID</span><span class="st">"</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a>    <span class="co"># Find posts containing keyword</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a>    <span class="va">POSTS=$(</span><span class="ex">wp</span> post list --s=<span class="st">"</span><span class="va">$KEYWORD</span><span class="st">"</span> --post_status=publish --format=ids<span class="va">)</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true"></a></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true"></a>    <span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$POSTS</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true"></a>        <span class="co"># Check if category already assigned</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true"></a>        <span class="va">HAS_CAT=$(</span><span class="ex">wp</span> post term list <span class="va">$post_id</span> category --field=term_id <span class="kw">|</span> <span class="fu">grep</span> -c <span class="st">"^</span><span class="va">${CAT_ID}</span><span class="st"><pre wp-pre-tag-4=""></pre>quot;</span><span class="va">)</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true"></a></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true"></a>        <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$HAS_CAT</span><span class="st">"</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"  Adding category </span><span class="va">$CAT_ID</span><span class="st"> to post </span><span class="va">$post_id</span><span class="st">"</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true"></a>            <span class="ex">wp</span> post term add <span class="va">$post_id</span> category <span class="va">$CAT_ID</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true"></a></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Auto-categorization complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="author-operations">Bulk Author Updates</h3>



<p>Reassign post authorship in bulk.</p>



<h4 class="wp-block-heading" id="change-post-authors">Change Post Authors</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co"># Reassign all posts from one author to another</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="va">OLD_AUTHOR_ID=</span>5</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a><span class="va">NEW_AUTHOR_ID=</span>1</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="ex">wp</span> post update <span class="va">$(</span><span class="ex">wp</span> post list --author=<span class="va">$OLD_AUTHOR_ID</span> --format=ids<span class="va">)</span> --post_author=<span class="va">$NEW_AUTHOR_ID</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="co"># Update posts by author email</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a><span class="va">OLD_EMAIL=</span><span class="st">"old@example.com"</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a><span class="va">NEW_AUTHOR_ID=</span>2</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a><span class="va">OLD_AUTHOR=$(</span><span class="ex">wp</span> user list --user_email=<span class="va">$OLD_EMAIL</span> --field=ID<span class="va">)</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a><span class="ex">wp</span> post update <span class="va">$(</span><span class="ex">wp</span> post list --author=<span class="va">$OLD_AUTHOR</span> --format=ids<span class="va">)</span> --post_author=<span class="va">$NEW_AUTHOR_ID</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="distribute-posts-across-authors">Distribute Posts Across Authors</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="co"># distribute-posts.sh - Evenly distribute posts across authors</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a><span class="va">AUTHORS=(</span>2 5 8 12<span class="va">)</span>  # <span class="ex">Author</span> IDs</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="va">POSTS=$(</span><span class="ex">wp</span> post list --post_status=publish --format=ids<span class="va">)</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a><span class="co"># Convert to array</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a><span class="va">POST_ARRAY=($POSTS)</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a><span class="va">TOTAL_POSTS=${#POST_ARRAY[@]}</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a><span class="va">AUTHOR_COUNT=${#AUTHORS[@]}</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Distributing </span><span class="va">$TOTAL_POSTS</span><span class="st"> posts across </span><span class="va">$AUTHOR_COUNT</span><span class="st"> authors..."</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a><span class="va">INDEX=</span>0</span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="st">"</span><span class="va">${POST_ARRAY[@]}</span><span class="st">"</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a>    <span class="va">AUTHOR_INDEX=$((</span>INDEX % AUTHOR_COUNT<span class="va">))</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a>    <span class="va">AUTHOR_ID=${AUTHORS[$AUTHOR_INDEX]}</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a>    <span class="ex">wp</span> post update <span class="va">$post_id</span> --post_author=<span class="va">$AUTHOR_ID</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a>    <span class="kw">((</span>INDEX++<span class="kw">))</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Post distribution complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="post-meta">Bulk Post Meta Operations</h3>



<p>Add, update, or delete custom fields across posts.</p>



<h4 class="wp-block-heading" id="add-meta-to-all-posts">Add Meta to All Posts</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co"># Add custom field to all posts</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a>    <span class="ex">wp</span> post meta add <span class="va">$post_id</span> featured_priority <span class="st">"normal"</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a><span class="co"># Add meta only to posts without it</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>    <span class="kw">if</span> ! <span class="ex">wp</span> post meta get <span class="va">$post_id</span> custom_field <span class="op">&amp;&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a>        <span class="ex">wp</span> post meta add <span class="va">$post_id</span> custom_field <span class="st">"default_value"</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="update-meta-in-bulk">Update Meta in Bulk</h4>



<div class="sourceCode" id="cb9">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co"># Update meta for posts in specific category</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a><span class="va">POSTS=$(</span><span class="ex">wp</span> post list --category_name=<span class="st">"premium"</span> --format=ids<span class="va">)</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$POSTS</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a>    <span class="ex">wp</span> post meta update <span class="va">$post_id</span> access_level <span class="st">"premium"</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a>    <span class="ex">wp</span> post meta update <span class="va">$post_id</span> show_ads <span class="st">"false"</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a><span class="co"># Conditional meta update</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a>    <span class="va">OLD_VALUE=$(</span><span class="ex">wp</span> post meta get <span class="va">$post_id</span> old_field <span class="op">2&gt;</span>/dev/null<span class="va">)</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-n</span> <span class="st">"</span><span class="va">$OLD_VALUE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a>        <span class="ex">wp</span> post meta add <span class="va">$post_id</span> new_field <span class="st">"</span><span class="va">$OLD_VALUE</span><span class="st">"</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a>        <span class="ex">wp</span> post meta delete <span class="va">$post_id</span> old_field</span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="clean-orphaned-meta">Clean Orphaned Meta</h4>



<div class="sourceCode" id="cb10">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a><span class="co"># clean-post-meta.sh - Remove meta from deleted posts</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Cleaning orphaned post meta..."</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a><span class="co"># SQL query to find orphaned meta</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a><span class="ex">wp</span> db query <span class="st">"</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a><span class="st">DELETE FROM wp_postmeta</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a><span class="st">WHERE post_id NOT IN (</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a><span class="st">    SELECT ID FROM wp_posts</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a><span class="st">)</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a><span class="st">"</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></a></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Orphaned post meta cleaned"</span></span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/support/article/custom-fields/">WordPress custom fields</a>.</p>



<h3 class="wp-block-heading" id="transformations">Content Transformation Operations</h3>



<p>Transform post content structure and format.</p>



<h4 class="wp-block-heading" id="bulk-content-search-replace">Bulk Content Search-Replace</h4>



<div class="sourceCode" id="cb11">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="co"># Replace text in all post content</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"old company name"</span> <span class="st">"new company name"</span> wp_posts --dry-run</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"old company name"</span> <span class="st">"new company name"</span> wp_posts</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a><span class="co"># Update image URLs</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"http://oldcdn.com"</span> <span class="st">"https://newcdn.com"</span> wp_posts</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a><span class="co"># Fix broken shortcodes</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"[old_shortcode"</span> <span class="st">"[new_shortcode"</span> wp_posts</span></code></pre>
</div>



<h4 class="wp-block-heading" id="add-content-prefixsuffix">Add Content Prefix/Suffix</h4>



<div class="sourceCode" id="cb12">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a><span class="co"># add-content-notice.sh - Add notice to all posts</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a><span class="va">NOTICE=</span><span class="st">'&lt;div class="post-notice"&gt;This article was published over a year ago.&lt;/div&gt;'</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true"></a><span class="co"># Get posts older than 1 year</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a><span class="va">POSTS=$(</span><span class="ex">wp</span> post list --before=<span class="st">"1 year ago"</span> --post_status=publish --format=ids<span class="va">)</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true"></a></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$POSTS</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true"></a>    <span class="va">CONTENT=$(</span><span class="ex">wp</span> post get <span class="va">$post_id</span> --field=post_content<span class="va">)</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true"></a></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true"></a>    <span class="co"># Check if notice already exists</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true"></a>    <span class="kw">if [[</span> <span class="ot">!</span> <span class="st">"</span><span class="va">$CONTENT</span><span class="st">"</span> =~ <span class="st">"post-notice"</span><span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true"></a>        <span class="va">NEW_CONTENT=</span><span class="st">"</span><span class="va">${NOTICE}${CONTENT}</span><span class="st">"</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true"></a></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true"></a>        <span class="ex">wp</span> post update <span class="va">$post_id</span> --post_content=<span class="st">"</span><span class="va">$NEW_CONTENT</span><span class="st">"</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Added notice to post </span><span class="va">$post_id</span><span class="st">"</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true"></a></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Content notices added"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="convert-post-types">Convert Post Types</h4>



<div class="sourceCode" id="cb13">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a><span class="co"># Convert posts to pages</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --post_type=post --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a>    <span class="ex">wp</span> post update <span class="va">$post_id</span> --post_type=page</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true"></a></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true"></a><span class="co"># Convert pages back to posts</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --post_type=page --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true"></a>    <span class="ex">wp</span> post update <span class="va">$post_id</span> --post_type=post --post_category=1</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="cleanup-operations">Bulk Post Cleanup</h3>



<p>Remove unwanted content and maintain database health.</p>



<h4 class="wp-block-heading" id="delete-posts-by-criteria">Delete Posts by Criteria</h4>



<div class="sourceCode" id="cb14">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true"></a><span class="co"># Delete all drafts older than 6 months</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true"></a><span class="ex">wp</span> post delete <span class="va">$(</span><span class="ex">wp</span> post list --post_status=draft --before=<span class="st">"6 months ago"</span> --format=ids<span class="va">)</span> --force</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true"></a><span class="co"># Delete empty posts</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true"></a><span class="ex">wp</span> post delete <span class="va">$(</span><span class="ex">wp</span> post list --post_content=<span class="st">""</span> --format=ids<span class="va">)</span> --force</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true"></a><span class="co"># Empty trash</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true"></a><span class="ex">wp</span> post delete <span class="va">$(</span><span class="ex">wp</span> post list --post_status=trash --format=ids<span class="va">)</span> --force</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true"></a></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true"></a><span class="co"># Delete posts with specific meta</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> post meta get <span class="va">$post_id</span> spam_flag <span class="op">2&gt;</span>/dev/null <span class="kw">|</span> <span class="fu">grep</span> -q <span class="st">"true"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true"></a>        <span class="ex">wp</span> post delete <span class="va">$post_id</span> --force</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Deleted spam post: </span><span class="va">$post_id</span><span class="st">"</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="clean-revisions">Clean Revisions</h4>



<div class="sourceCode" id="cb15">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true"></a><span class="co"># Delete all revisions</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true"></a><span class="ex">wp</span> post delete <span class="va">$(</span><span class="ex">wp</span> post list --post_type=revision --format=ids<span class="va">)</span> --force</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true"></a><span class="co"># Keep only last 5 revisions per post (requires custom logic)</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --format=ids<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true"></a>    <span class="co"># Get revision IDs</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true"></a>    <span class="va">REVISIONS=$(</span><span class="ex">wp</span> post list --post_type=revision --post_parent=<span class="va">$post_id</span> --orderby=date --order=DESC --format=ids<span class="va">)</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true"></a></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true"></a>    <span class="co"># Convert to array</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true"></a>    <span class="va">REV_ARRAY=($REVISIONS)</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true"></a></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true"></a>    <span class="co"># Delete all but first 5</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="va">${#REV_ARRAY[@]}</span> <span class="ot">-gt</span> 5<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true"></a>        <span class="va">REVISIONS_TO_DELETE=</span><span class="st">"</span><span class="va">${REV_ARRAY[@]:5}</span><span class="st">"</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true"></a>        <span class="ex">wp</span> post delete <span class="va">$REVISIONS_TO_DELETE</span> --force</span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="scheduled-operations">Scheduled Content Operations</h3>



<p>Automate recurring bulk content tasks.</p>



<h4 class="wp-block-heading" id="auto-publish-scheduled-script">Auto-Publish Scheduled Script</h4>



<div class="sourceCode" id="cb16">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true"></a><span class="co"># auto-publish-oldest-draft.sh - Publish oldest draft daily</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true"></a><span class="va">MAX_POSTS=${1:-</span>1<span class="va">}</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Publishing up to </span><span class="va">$MAX_POSTS</span><span class="st"> draft posts..."</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true"></a></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true"></a><span class="va">DRAFTS=$(</span><span class="ex">wp</span> post list <span class="kw">\</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true"></a>    <span class="ex">--post_status</span>=draft <span class="kw">\</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true"></a>    <span class="ex">--orderby</span>=date <span class="kw">\</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true"></a>    <span class="ex">--order</span>=ASC <span class="kw">\</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true"></a>    <span class="ex">--posts_per_page</span>=<span class="va">$MAX_POSTS</span> <span class="kw">\</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true"></a>    <span class="ex">--format</span>=ids<span class="va">)</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true"></a></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$DRAFTS</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"No drafts available"</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true"></a>    <span class="bu">exit</span> 0</span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true"></a></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$DRAFTS</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true"></a>    <span class="va">TITLE=$(</span><span class="ex">wp</span> post get <span class="va">$post_id</span> --field=post_title<span class="va">)</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Publishing: </span><span class="va">$TITLE</span><span class="st">"</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true"></a></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true"></a>    <span class="ex">wp</span> post update <span class="va">$post_id</span> <span class="kw">\</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true"></a>        <span class="ex">--post_status</span>=publish <span class="kw">\</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true"></a>        <span class="ex">--post_date</span>=<span class="st">"</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true"></a></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Publishing complete"</span></span></code></pre>
</div>



<p>Schedule with cron:</p>



<div class="sourceCode" id="cb17">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true"></a><span class="co"># Publish 1 draft daily at 9 AM</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true"></a><span class="ex">0</span> 9 * * * /usr/local/bin/auto-publish-oldest-draft.sh 1</span></code></pre>
</div>



<h4 class="wp-block-heading" id="monthly-content-audit">Monthly Content Audit</h4>



<div class="sourceCode" id="cb18">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true"></a><span class="co"># monthly-content-audit.sh</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true"></a></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true"></a><span class="va">REPORT=</span><span class="st">"/tmp/content-audit-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m<span class="va">)</span><span class="st">.txt"</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true"></a></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true"></a><span class="kw">{</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"WordPress Content Audit Report"</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Generated: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"=============================="</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true"></a></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Total Posts: </span><span class="va">$(</span><span class="ex">wp</span> post list --post_type=post --format=count<span class="va">)</span><span class="st">"</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Published: </span><span class="va">$(</span><span class="ex">wp</span> post list --post_status=publish --format=count<span class="va">)</span><span class="st">"</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Drafts: </span><span class="va">$(</span><span class="ex">wp</span> post list --post_status=draft --format=count<span class="va">)</span><span class="st">"</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Scheduled: </span><span class="va">$(</span><span class="ex">wp</span> post list --post_status=future --format=count<span class="va">)</span><span class="st">"</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true"></a></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Posts by Category:"</span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true"></a>    <span class="ex">wp</span> term list category --fields=name,count --format=table</span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true"></a></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Posts Without Categories:"</span></span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true"></a>    <span class="ex">wp</span> post list --category=0 --format=count</span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true"></a></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Posts Without Tags:"</span></span>
<span id="cb18-27"><a href="#cb18-27" aria-hidden="true"></a>    <span class="kw">for</span> <span class="ex">post_id</span> in <span class="va">$(</span><span class="ex">wp</span> post list --format=ids <span class="kw">|</span> <span class="fu">head</span> -100<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb18-28"><a href="#cb18-28" aria-hidden="true"></a>        <span class="va">TAG_COUNT=$(</span><span class="ex">wp</span> post term list <span class="va">$post_id</span> post_tag --format=count<span class="va">)</span></span>
<span id="cb18-29"><a href="#cb18-29" aria-hidden="true"></a>        [ <span class="st">"</span><span class="va">$TAG_COUNT</span><span class="st">"</span> <span class="ex">-eq</span> 0 ] <span class="kw">&amp;&amp;</span> <span class="kw">((</span>NO_TAGS++<span class="kw">))</span></span>
<span id="cb18-30"><a href="#cb18-30" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb18-31"><a href="#cb18-31" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"</span><span class="va">${NO_TAGS:-</span>0<span class="va">}</span><span class="st"> posts"</span></span>
<span id="cb18-32"><a href="#cb18-32" aria-hidden="true"></a></span>
<span id="cb18-33"><a href="#cb18-33" aria-hidden="true"></a><span class="kw">}</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$REPORT</span><span class="st">"</span></span>
<span id="cb18-34"><a href="#cb18-34" aria-hidden="true"></a></span>
<span id="cb18-35"><a href="#cb18-35" aria-hidden="true"></a><span class="co"># Email report</span></span>
<span id="cb18-36"><a href="#cb18-36" aria-hidden="true"></a><span class="ex">mail</span> -s <span class="st">"Monthly Content Audit"</span> admin@example.com <span class="op">&lt;</span> <span class="st">"</span><span class="va">$REPORT</span><span class="st">"</span></span>
<span id="cb18-37"><a href="#cb18-37" aria-hidden="true"></a></span>
<span id="cb18-38"><a href="#cb18-38" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Audit report sent"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have advanced bulk content operation skills for WordPress at scale.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: Basic bulk operations</p>



<ul class="wp-block-list">
<li>Practice post status updates</li>



<li>Master taxonomy assignments</li>



<li>Update post authors</li>
</ul>



<p><strong>Week 2</strong>: Advanced transformations</p>



<ul class="wp-block-list">
<li>Content search-replace</li>



<li>Meta field operations</li>



<li>Post type conversions</li>
</ul>



<p><strong>Week 3</strong>: Cleanup automation</p>



<ul class="wp-block-list">
<li>Delete unwanted content</li>



<li>Manage revisions</li>



<li>Orphaned data cleanup</li>
</ul>



<p><strong>Week 4</strong>: Scheduled workflows</p>



<ul class="wp-block-list">
<li>Auto-publishing scripts</li>



<li>Content audits</li>



<li>Maintenance automation</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Custom Post Type Bulk Operations</a></strong> &#8211; Advanced CPT management</li>



<li><strong><a href="#">Multi-Site Content Sync</a></strong> &#8211; Network-wide operations</li>



<li><strong><a href="#">AI Content Enhancement</a></strong> &#8211; Automated content improvements</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download bulk operation scripts</a></strong> including:</p>



<ul class="wp-block-list">
<li>Complete automation toolkit</li>



<li>Content transformation scripts</li>



<li>Cleanup utilities</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>Content management strategies</li>



<li>Automation best practices</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>WP-CLI bulk content operations transform WordPress content management from manual drudgery into fast, automated workflows that handle any scale.</p>



<p>What we covered:</p>



<p>✅ Bulk post status and publication management <br>✅ Taxonomy assignment and reorganization <br>✅ Author reassignment and distribution <br>✅ Post meta bulk operations <br>✅ Content transformation and cleanup <br>✅ Scheduled and automated workflows</p>



<p>Master these techniques, and you’ll manage thousands of WordPress posts as easily as managing ten—whether publishing content at scale or maintaining large content archives.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">WordPress content migration</a> or <a href="#">automated content workflows</a>.</p>



<p><strong>Questions about bulk content operations in WordPress?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other WordPress content managers.</p>
<p>The post <a href="https://wpclimastery.com/blog/bulk-content-operations-in-wordpress-wp-cli-advanced-techniques/">Bulk Content Operations in WordPress: WP-CLI Advanced Techniques</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Building a Complete WordPress Deployment System with WP-CLI (Real Project)</title>
		<link>https://wpclimastery.com/blog/building-a-complete-wordpress-deployment-system-with-wp-cli-real-project/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Fri, 30 Jan 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Real-World WP-CLI Projects]]></category>
		<category><![CDATA[complete deployment automation]]></category>
		<category><![CDATA[devops wordpress]]></category>
		<category><![CDATA[wordpress automation project]]></category>
		<category><![CDATA[wordpress deployment system]]></category>
		<category><![CDATA[wp-cli project]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=160</guid>

					<description><![CDATA[<p>Professional WordPress deployments require coordinating server provisioning, WordPress installation, plugin configuration, database migrations, zero-downtime releases, automated backups, health monitoring, and rollback capabilities. Managing these manually across development, staging, and production...</p>
<p>The post <a href="https://wpclimastery.com/blog/building-a-complete-wordpress-deployment-system-with-wp-cli-real-project/">Building a Complete WordPress Deployment System with WP-CLI (Real Project)</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Professional WordPress deployments require coordinating server provisioning, WordPress installation, plugin configuration, database migrations, zero-downtime releases, automated backups, health monitoring, and rollback capabilities. Managing these manually across development, staging, and production environments is error-prone and time-consuming.</p>



<p>A complete WordPress deployment system automates the entire lifecycle—provision servers, install WordPress, deploy code changes, run migrations, monitor health, and rollback failures—all with single commands executed by WP-CLI and Bash scripts.</p>



<p>In this guide, you’ll build a production-ready WordPress deployment system used by professional development teams, integrating server provisioning, automated deployments, monitoring, and disaster recovery into one cohesive system.</p>



<h3 class="wp-block-heading" id="architecture">System Architecture Overview</h3>



<p>Understand the complete deployment system components and workflow.</p>



<h4 class="wp-block-heading" id="deployment-system-components">Deployment System Components</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>┌─────────────────────┐</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a>│  <span class="ex">Version</span> Control    │  ← Git repository (source of truth)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a>│      <span class="kw">(</span><span class="ex">Git</span><span class="kw">)</span>          │</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a>└──────────┬──────────┘</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a>           │</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a>           ▼</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a>┌─────────────────────┐</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a>│  <span class="ex">CI/CD</span> Pipeline     │  ← GitHub Actions/GitLab CI</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a>│   <span class="kw">(</span><span class="ex">Automated</span><span class="kw">)</span>       │</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a>└──────────┬──────────┘</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a>           │</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a>           ▼</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a>┌─────────────────────┐</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a>│ <span class="ex">Deployment</span> Scripts  │  ← WP-CLI + Bash automation</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true"></a>│    <span class="kw">(</span><span class="ex">This</span> System<span class="kw">)</span>    │</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true"></a>└──────────┬──────────┘</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true"></a>           │</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true"></a>    ┌──────┴──────┐</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true"></a>    │             │</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true"></a>    ▼             ▼</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true"></a>┌────────┐   ┌────────┐</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true"></a>│<span class="ex">Staging</span> │   │  Prod  │  ← WordPress environments</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true"></a>└────────┘   └────────┘</span></code></pre>
</div>



<h4 class="wp-block-heading" id="system-features">System Features</h4>



<p><strong>Server provisioning</strong>: Automated WordPress server setup from scratch.</p>



<p><strong>Zero-downtime deploys</strong>: Release code without taking site offline.</p>



<p><strong>Database migrations</strong>: Automatic schema changes with rollback.</p>



<p><strong>Health monitoring</strong>: Continuous uptime and performance checks.</p>



<p><strong>Automatic backups</strong>: Pre-deployment snapshots with retention policies.</p>



<p><strong>One-command rollback</strong>: Instantly revert failed deployments.</p>



<p>Learn about <a href="https://aws.amazon.com/devops/what-is-devops/">DevOps deployment patterns</a>.</p>



<h3 class="wp-block-heading" id="project-structure">Project Structure and Setup</h3>



<p>Organize the deployment system codebase.</p>



<h4 class="wp-block-heading" id="directory-structure">Directory Structure</h4>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="ex">wordpress-deploy-system/</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>├── <span class="ex">bin/</span>                      # Executable scripts</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a>│   ├── <span class="ex">deploy</span>                # Main deployment command</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a>│   ├── <span class="ex">provision</span>             # Server provisioning</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a>│   ├── <span class="ex">backup</span>                # Backup management</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a>│   ├── <span class="ex">rollback</span>              # Rollback deployments</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a>│   └── <span class="ex">monitor</span>               # Health monitoring</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a>├── <span class="ex">lib/</span>                      # Reusable functions</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a>│   ├── <span class="ex">common.sh</span>             # Shared utilities</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a>│   ├── <span class="ex">deploy.sh</span>             # Deployment logic</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a>│   ├── <span class="ex">database.sh</span>           # DB operations</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a>│   └── <span class="ex">wordpress.sh</span>          # WordPress operations</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a>├── <span class="ex">config/</span>                   # Configuration files</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true"></a>│   ├── <span class="ex">environments/</span>         # Environment-specific configs</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true"></a>│   │   ├── <span class="ex">development.conf</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true"></a>│   │   ├── <span class="ex">staging.conf</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true"></a>│   │   └── <span class="ex">production.conf</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true"></a>│   └── <span class="ex">deploy.conf</span>           # Global deployment config</span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true"></a>├── <span class="ex">migrations/</span>               # Database migrations</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true"></a>│   ├── <span class="ex">001-initial-schema.sql</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true"></a>│   └── <span class="ex">002-add-custom-tables.sql</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true"></a>├── <span class="ex">hooks/</span>                    # Deployment hooks</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true"></a>│   ├── <span class="ex">pre-deploy.sh</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true"></a>│   ├── <span class="ex">post-deploy.sh</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true"></a>│   └── <span class="ex">health-check.sh</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true"></a>├── <span class="ex">logs/</span>                     # Deployment logs</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true"></a>└── <span class="ex">backups/</span>                  # Backup storage</span></code></pre>
</div>



<h4 class="wp-block-heading" id="installation-script">Installation Script</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># install.sh - Set up deployment system</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="va">INSTALL_DIR=</span><span class="st">"/opt/wordpress-deploy"</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Installing WordPress Deployment System"</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"======================================="</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a><span class="co"># Create directory structure</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a><span class="fu">sudo</span> mkdir -p <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">"</span>/<span class="dt">{bin,lib,config/environments,migrations,hooks,logs,backups}</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a><span class="co"># Copy files</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a><span class="fu">sudo</span> cp -r bin/* <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">/bin/"</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a><span class="fu">sudo</span> cp -r lib/* <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">/lib/"</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a><span class="fu">sudo</span> cp -r config/* <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">/config/"</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a><span class="co"># Make scripts executable</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a><span class="fu">sudo</span> chmod +x <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">"</span>/bin/*</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a><span class="fu">sudo</span> chmod +x <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">"</span>/hooks/*</span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a><span class="co"># Add to PATH</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"export PATH=</span><span class="dt">\$</span><span class="st">PATH:</span><span class="va">$INSTALL_DIR</span><span class="st">/bin"</span> <span class="kw">|</span> <span class="fu">sudo</span> tee -a /etc/profile.d/wordpress-deploy.sh</span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a><span class="co"># Install WP-CLI if not present</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a><span class="kw">if</span> ! <span class="bu">command</span> -v wp <span class="op">&amp;&gt;</span> /dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Installing WP-CLI..."</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true"></a>    <span class="ex">curl</span> -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar</span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a>    <span class="fu">sudo</span> mv wp-cli.phar /usr/local/bin/wp</span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a>    <span class="fu">sudo</span> chmod +x /usr/local/bin/wp</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Installation complete"</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Usage: deploy &lt;environment&gt; &lt;release&gt;"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="provisioning">Server Provisioning Automation</h3>



<p>Automate complete WordPress server setup.</p>



<h4 class="wp-block-heading" id="provisioning-script">Provisioning Script</h4>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="co"># bin/provision - Provision WordPress server</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/common.sh"</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>staging<span class="va">}</span><span class="st">"</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a><span class="va">CONFIG_FILE=</span><span class="st">"</span><span class="va">$CONFIG_DIR</span><span class="st">/environments/</span><span class="va">$ENVIRONMENT</span><span class="st">.conf"</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Configuration not found: </span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true"></a></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Provisioning WordPress server for: </span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true"></a></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true"></a><span class="co"># Update system packages</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Updating system packages..."</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true"></a><span class="fu">sudo</span> apt-get update</span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true"></a><span class="fu">sudo</span> apt-get upgrade -y</span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true"></a></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true"></a><span class="co"># Install LAMP stack</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Installing LAMP stack..."</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true"></a><span class="fu">sudo</span> apt-get install -y <span class="kw">\</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true"></a>    <span class="ex">nginx</span> <span class="kw">\</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true"></a>    <span class="ex">mysql-server</span> <span class="kw">\</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true"></a>    <span class="ex">php8.1-fpm</span> <span class="kw">\</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true"></a>    <span class="ex">php8.1-mysql</span> <span class="kw">\</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true"></a>    <span class="ex">php8.1-xml</span> <span class="kw">\</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true"></a>    <span class="ex">php8.1-mbstring</span> <span class="kw">\</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true"></a>    <span class="ex">php8.1-curl</span> <span class="kw">\</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true"></a>    <span class="ex">php8.1-zip</span> <span class="kw">\</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true"></a>    <span class="ex">php8.1-gd</span> <span class="kw">\</span></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true"></a>    <span class="ex">php8.1-intl</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true"></a></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true"></a><span class="co"># Configure Nginx</span></span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Configuring Nginx..."</span></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true"></a><span class="fu">sudo</span> tee /etc/nginx/sites-available/wordpress <span class="op">&lt;&lt;EOF</span></span>
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true"></a>server {</span>
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true"></a>    listen 80;</span>
<span id="cb4-43"><a href="#cb4-43" aria-hidden="true"></a>    server_name <span class="va">$SERVER_NAME</span>;</span>
<span id="cb4-44"><a href="#cb4-44" aria-hidden="true"></a>    root <span class="va">$DEPLOY_PATH</span>/current;</span>
<span id="cb4-45"><a href="#cb4-45" aria-hidden="true"></a>    index index.php;</span>
<span id="cb4-46"><a href="#cb4-46" aria-hidden="true"></a></span>
<span id="cb4-47"><a href="#cb4-47" aria-hidden="true"></a>    location / {</span>
<span id="cb4-48"><a href="#cb4-48" aria-hidden="true"></a>        try_files <span class="dt">\$</span>uri <span class="dt">\$</span>uri/ /index.php?<span class="dt">\$</span>args;</span>
<span id="cb4-49"><a href="#cb4-49" aria-hidden="true"></a>    }</span>
<span id="cb4-50"><a href="#cb4-50" aria-hidden="true"></a></span>
<span id="cb4-51"><a href="#cb4-51" aria-hidden="true"></a>    location ~ \.php$ {</span>
<span id="cb4-52"><a href="#cb4-52" aria-hidden="true"></a>        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;</span>
<span id="cb4-53"><a href="#cb4-53" aria-hidden="true"></a>        fastcgi_index index.php;</span>
<span id="cb4-54"><a href="#cb4-54" aria-hidden="true"></a>        include fastcgi_params;</span>
<span id="cb4-55"><a href="#cb4-55" aria-hidden="true"></a>        fastcgi_param SCRIPT_FILENAME <span class="dt">\$</span>document_root<span class="dt">\$</span>fastcgi_script_name;</span>
<span id="cb4-56"><a href="#cb4-56" aria-hidden="true"></a>    }</span>
<span id="cb4-57"><a href="#cb4-57" aria-hidden="true"></a>}</span>
<span id="cb4-58"><a href="#cb4-58" aria-hidden="true"></a><span class="op">EOF</span></span>
<span id="cb4-59"><a href="#cb4-59" aria-hidden="true"></a></span>
<span id="cb4-60"><a href="#cb4-60" aria-hidden="true"></a><span class="fu">sudo</span> ln -sf /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/</span>
<span id="cb4-61"><a href="#cb4-61" aria-hidden="true"></a><span class="fu">sudo</span> nginx -t <span class="kw">&amp;&amp;</span> <span class="fu">sudo</span> systemctl reload nginx</span>
<span id="cb4-62"><a href="#cb4-62" aria-hidden="true"></a></span>
<span id="cb4-63"><a href="#cb4-63" aria-hidden="true"></a><span class="co"># Create deployment directories</span></span>
<span id="cb4-64"><a href="#cb4-64" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating deployment directories..."</span></span>
<span id="cb4-65"><a href="#cb4-65" aria-hidden="true"></a><span class="fu">sudo</span> mkdir -p <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span>/<span class="dt">{releases,shared}</span></span>
<span id="cb4-66"><a href="#cb4-66" aria-hidden="true"></a><span class="fu">sudo</span> mkdir -p <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/shared"</span>/<span class="dt">{wp-content/uploads,logs}</span></span>
<span id="cb4-67"><a href="#cb4-67" aria-hidden="true"></a></span>
<span id="cb4-68"><a href="#cb4-68" aria-hidden="true"></a><span class="co"># Set permissions</span></span>
<span id="cb4-69"><a href="#cb4-69" aria-hidden="true"></a><span class="fu">sudo</span> chown -R www-data:www-data <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span></span>
<span id="cb4-70"><a href="#cb4-70" aria-hidden="true"></a><span class="fu">sudo</span> chmod -R 755 <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span></span>
<span id="cb4-71"><a href="#cb4-71" aria-hidden="true"></a></span>
<span id="cb4-72"><a href="#cb4-72" aria-hidden="true"></a><span class="co"># Create MySQL database</span></span>
<span id="cb4-73"><a href="#cb4-73" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating WordPress database..."</span></span>
<span id="cb4-74"><a href="#cb4-74" aria-hidden="true"></a><span class="fu">sudo</span> mysql <span class="op">&lt;&lt;EOF</span></span>
<span id="cb4-75"><a href="#cb4-75" aria-hidden="true"></a>CREATE DATABASE IF NOT EXISTS <span class="va">$DB_NAME</span>;</span>
<span id="cb4-76"><a href="#cb4-76" aria-hidden="true"></a>CREATE USER IF NOT EXISTS '<span class="va">$DB_USER</span>'@'localhost' IDENTIFIED BY '<span class="va">$DB_PASS</span>';</span>
<span id="cb4-77"><a href="#cb4-77" aria-hidden="true"></a>GRANT ALL PRIVILEGES ON <span class="va">$DB_NAME</span>.* TO '<span class="va">$DB_USER</span>'@'localhost';</span>
<span id="cb4-78"><a href="#cb4-78" aria-hidden="true"></a>FLUSH PRIVILEGES;</span>
<span id="cb4-79"><a href="#cb4-79" aria-hidden="true"></a><span class="op">EOF</span></span>
<span id="cb4-80"><a href="#cb4-80" aria-hidden="true"></a></span>
<span id="cb4-81"><a href="#cb4-81" aria-hidden="true"></a><span class="co"># Install WordPress</span></span>
<span id="cb4-82"><a href="#cb4-82" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Installing WordPress..."</span></span>
<span id="cb4-83"><a href="#cb4-83" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span></span>
<span id="cb4-84"><a href="#cb4-84" aria-hidden="true"></a></span>
<span id="cb4-85"><a href="#cb4-85" aria-hidden="true"></a><span class="ex">wp</span> core download --path=initial-install</span>
<span id="cb4-86"><a href="#cb4-86" aria-hidden="true"></a><span class="bu">cd</span> initial-install</span>
<span id="cb4-87"><a href="#cb4-87" aria-hidden="true"></a></span>
<span id="cb4-88"><a href="#cb4-88" aria-hidden="true"></a><span class="ex">wp</span> config create <span class="kw">\</span></span>
<span id="cb4-89"><a href="#cb4-89" aria-hidden="true"></a>    <span class="ex">--dbname</span>=<span class="st">"</span><span class="va">$DB_NAME</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-90"><a href="#cb4-90" aria-hidden="true"></a>    <span class="ex">--dbuser</span>=<span class="st">"</span><span class="va">$DB_USER</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-91"><a href="#cb4-91" aria-hidden="true"></a>    <span class="ex">--dbpass</span>=<span class="st">"</span><span class="va">$DB_PASS</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-92"><a href="#cb4-92" aria-hidden="true"></a>    <span class="ex">--dbhost</span>=localhost</span>
<span id="cb4-93"><a href="#cb4-93" aria-hidden="true"></a></span>
<span id="cb4-94"><a href="#cb4-94" aria-hidden="true"></a><span class="ex">wp</span> core install <span class="kw">\</span></span>
<span id="cb4-95"><a href="#cb4-95" aria-hidden="true"></a>    <span class="ex">--url</span>=<span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-96"><a href="#cb4-96" aria-hidden="true"></a>    <span class="ex">--title</span>=<span class="st">"</span><span class="va">$SITE_TITLE</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-97"><a href="#cb4-97" aria-hidden="true"></a>    <span class="ex">--admin_user</span>=<span class="st">"</span><span class="va">$ADMIN_USER</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-98"><a href="#cb4-98" aria-hidden="true"></a>    <span class="ex">--admin_password</span>=<span class="st">"</span><span class="va">$ADMIN_PASS</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-99"><a href="#cb4-99" aria-hidden="true"></a>    <span class="ex">--admin_email</span>=<span class="st">"</span><span class="va">$ADMIN_EMAIL</span><span class="st">"</span></span>
<span id="cb4-100"><a href="#cb4-100" aria-hidden="true"></a></span>
<span id="cb4-101"><a href="#cb4-101" aria-hidden="true"></a><span class="co"># Move to shared directory</span></span>
<span id="cb4-102"><a href="#cb4-102" aria-hidden="true"></a><span class="fu">mv</span> wp-content/uploads/* <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/shared/wp-content/uploads/"</span></span>
<span id="cb4-103"><a href="#cb4-103" aria-hidden="true"></a><span class="fu">mv</span> wp-config.php <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/shared/"</span></span>
<span id="cb4-104"><a href="#cb4-104" aria-hidden="true"></a></span>
<span id="cb4-105"><a href="#cb4-105" aria-hidden="true"></a><span class="co"># Install SSL certificate (Let's Encrypt)</span></span>
<span id="cb4-106"><a href="#cb4-106" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$SSL_ENABLED</span><span class="st">"</span> <span class="ot">=</span> <span class="st">"true"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb4-107"><a href="#cb4-107" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"Installing SSL certificate..."</span></span>
<span id="cb4-108"><a href="#cb4-108" aria-hidden="true"></a>    <span class="fu">sudo</span> apt-get install -y certbot python3-certbot-nginx</span>
<span id="cb4-109"><a href="#cb4-109" aria-hidden="true"></a>    <span class="fu">sudo</span> certbot --nginx -d <span class="st">"</span><span class="va">$SERVER_NAME</span><span class="st">"</span> --non-interactive --agree-tos -m <span class="st">"</span><span class="va">$ADMIN_EMAIL</span><span class="st">"</span></span>
<span id="cb4-110"><a href="#cb4-110" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-111"><a href="#cb4-111" aria-hidden="true"></a></span>
<span id="cb4-112"><a href="#cb4-112" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"✓ Server provisioning complete"</span></span>
<span id="cb4-113"><a href="#cb4-113" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"WordPress URL: </span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb4-114"><a href="#cb4-114" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Admin user: </span><span class="va">$ADMIN_USER</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="environment-configuration-template">Environment Configuration Template</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co"># config/environments/production.conf</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a><span class="co"># Server settings</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">SERVER_NAME=</span><span class="st">"example.com"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="va">SITE_URL=</span><span class="st">"https://example.com"</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a><span class="va">SITE_TITLE=</span><span class="st">"Production Site"</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a><span class="co"># Deployment paths</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a><span class="va">DEPLOY_PATH=</span><span class="st">"/var/www/production"</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a><span class="va">RELEASE_DIR=</span><span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/releases"</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a><span class="va">SHARED_DIR=</span><span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/shared"</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a><span class="va">CURRENT_LINK=</span><span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/current"</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a><span class="co"># Database credentials</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a><span class="va">DB_NAME=</span><span class="st">"wp_production"</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a><span class="va">DB_USER=</span><span class="st">"wp_user"</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a><span class="va">DB_PASS=</span><span class="st">"strong-password-here"</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a><span class="va">DB_HOST=</span><span class="st">"localhost"</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true"></a><span class="co"># WordPress admin</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true"></a><span class="va">ADMIN_USER=</span><span class="st">"admin"</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true"></a><span class="va">ADMIN_PASS=</span><span class="st">"admin-password-here"</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true"></a><span class="va">ADMIN_EMAIL=</span><span class="st">"admin@example.com"</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true"></a></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true"></a><span class="co"># Git repository</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true"></a><span class="va">GIT_REPO=</span><span class="st">"git@github.com:yourcompany/wordpress-site.git"</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true"></a><span class="va">GIT_BRANCH=</span><span class="st">"main"</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true"></a></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true"></a><span class="co"># Deployment settings</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true"></a><span class="va">KEEP_RELEASES=</span>5</span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true"></a><span class="va">BACKUP_RETENTION_DAYS=</span>30</span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true"></a><span class="va">SSL_ENABLED=</span>true</span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true"></a></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true"></a><span class="co"># Notifications</span></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true"></a><span class="va">SLACK_WEBHOOK=</span><span class="st">"https://hooks.slack.com/services/YOUR/WEBHOOK/URL"</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true"></a><span class="va">EMAIL_NOTIFICATIONS=</span><span class="st">"team@example.com"</span></span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/about/requirements/">WordPress server requirements</a>.</p>



<h3 class="wp-block-heading" id="zero-downtime">Zero-Downtime Deployment Implementation</h3>



<p>Deploy code changes without taking site offline.</p>



<h4 class="wp-block-heading" id="main-deployment-script">Main Deployment Script</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="co"># bin/deploy - Main deployment command</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/common.sh"</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/deploy.sh"</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>staging<span class="va">}</span><span class="st">"</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a><span class="va">RELEASE_TAG=</span><span class="st">"</span><span class="va">${2:-</span>HEAD<span class="va">}</span><span class="st">"</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a><span class="va">CONFIG_FILE=</span><span class="st">"</span><span class="va">$CONFIG_DIR</span><span class="st">/environments/</span><span class="va">$ENVIRONMENT</span><span class="st">.conf"</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Configuration not found: </span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== WordPress Deployment Started ==="</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Environment: </span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Release: </span><span class="va">$RELEASE_TAG</span><span class="st">"</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Time: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true"></a></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true"></a><span class="co"># Pre-deployment checks</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running pre-deployment checks..."</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true"></a><span class="ex">run_hook</span> <span class="st">"pre-deploy"</span> <span class="kw">||</span> <span class="ex">error</span> <span class="st">"Pre-deployment checks failed"</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true"></a></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true"></a><span class="co"># Create backup</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating pre-deployment backup..."</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true"></a><span class="st">"</span><span class="va">$BIN_DIR</span><span class="st">/backup"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="kw">||</span> <span class="ex">error</span> <span class="st">"Backup failed"</span></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true"></a></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true"></a><span class="co"># Prepare new release</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true"></a><span class="va">RELEASE_ID=$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true"></a><span class="va">RELEASE_PATH=</span><span class="st">"</span><span class="va">$RELEASE_DIR</span><span class="st">/</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true"></a></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating release: </span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true"></a></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true"></a><span class="co"># Clone code from Git</span></span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Cloning repository..."</span></span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true"></a><span class="fu">git</span> clone --depth 1 --branch <span class="st">"</span><span class="va">$GIT_BRANCH</span><span class="st">"</span> <span class="st">"</span><span class="va">$GIT_REPO</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true"></a></span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true"></a><span class="co"># Install dependencies</span></span>
<span id="cb6-45"><a href="#cb6-45" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Installing dependencies..."</span></span>
<span id="cb6-46"><a href="#cb6-46" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> composer.json<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb6-47"><a href="#cb6-47" aria-hidden="true"></a>    <span class="ex">composer</span> install --no-dev --optimize-autoloader</span>
<span id="cb6-48"><a href="#cb6-48" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb6-49"><a href="#cb6-49" aria-hidden="true"></a></span>
<span id="cb6-50"><a href="#cb6-50" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> package.json<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb6-51"><a href="#cb6-51" aria-hidden="true"></a>    <span class="ex">npm</span> ci --production</span>
<span id="cb6-52"><a href="#cb6-52" aria-hidden="true"></a>    <span class="ex">npm</span> run build</span>
<span id="cb6-53"><a href="#cb6-53" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb6-54"><a href="#cb6-54" aria-hidden="true"></a></span>
<span id="cb6-55"><a href="#cb6-55" aria-hidden="true"></a><span class="co"># Link shared directories</span></span>
<span id="cb6-56"><a href="#cb6-56" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Linking shared resources..."</span></span>
<span id="cb6-57"><a href="#cb6-57" aria-hidden="true"></a><span class="fu">ln</span> -nfs <span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">/wp-content/uploads"</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">/wp-content/uploads"</span></span>
<span id="cb6-58"><a href="#cb6-58" aria-hidden="true"></a><span class="fu">ln</span> -nfs <span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">/wp-config.php"</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">/wp-config.php"</span></span>
<span id="cb6-59"><a href="#cb6-59" aria-hidden="true"></a></span>
<span id="cb6-60"><a href="#cb6-60" aria-hidden="true"></a><span class="co"># Run database migrations</span></span>
<span id="cb6-61"><a href="#cb6-61" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running database migrations..."</span></span>
<span id="cb6-62"><a href="#cb6-62" aria-hidden="true"></a><span class="ex">run_migrations</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span> <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb6-63"><a href="#cb6-63" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Database migration failed"</span></span>
<span id="cb6-64"><a href="#cb6-64" aria-hidden="true"></a>    <span class="ex">rollback_deployment</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-65"><a href="#cb6-65" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb6-66"><a href="#cb6-66" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb6-67"><a href="#cb6-67" aria-hidden="true"></a></span>
<span id="cb6-68"><a href="#cb6-68" aria-hidden="true"></a><span class="co"># Health check on new release</span></span>
<span id="cb6-69"><a href="#cb6-69" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running health checks..."</span></span>
<span id="cb6-70"><a href="#cb6-70" aria-hidden="true"></a><span class="ex">test_release</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span> <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb6-71"><a href="#cb6-71" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Health checks failed"</span></span>
<span id="cb6-72"><a href="#cb6-72" aria-hidden="true"></a>    <span class="ex">rollback_deployment</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-73"><a href="#cb6-73" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb6-74"><a href="#cb6-74" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb6-75"><a href="#cb6-75" aria-hidden="true"></a></span>
<span id="cb6-76"><a href="#cb6-76" aria-hidden="true"></a><span class="co"># Atomic switch to new release</span></span>
<span id="cb6-77"><a href="#cb6-77" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Switching to new release..."</span></span>
<span id="cb6-78"><a href="#cb6-78" aria-hidden="true"></a><span class="fu">ln</span> -nfs <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb6-79"><a href="#cb6-79" aria-hidden="true"></a></span>
<span id="cb6-80"><a href="#cb6-80" aria-hidden="true"></a><span class="co"># Post-deployment tasks</span></span>
<span id="cb6-81"><a href="#cb6-81" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running post-deployment tasks..."</span></span>
<span id="cb6-82"><a href="#cb6-82" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb6-83"><a href="#cb6-83" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb6-84"><a href="#cb6-84" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb6-85"><a href="#cb6-85" aria-hidden="true"></a></span>
<span id="cb6-86"><a href="#cb6-86" aria-hidden="true"></a><span class="ex">run_hook</span> <span class="st">"post-deploy"</span></span>
<span id="cb6-87"><a href="#cb6-87" aria-hidden="true"></a></span>
<span id="cb6-88"><a href="#cb6-88" aria-hidden="true"></a><span class="co"># Cleanup old releases</span></span>
<span id="cb6-89"><a href="#cb6-89" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Cleaning up old releases..."</span></span>
<span id="cb6-90"><a href="#cb6-90" aria-hidden="true"></a><span class="ex">cleanup_releases</span> <span class="st">"</span><span class="va">$RELEASE_DIR</span><span class="st">"</span> <span class="st">"</span><span class="va">$KEEP_RELEASES</span><span class="st">"</span></span>
<span id="cb6-91"><a href="#cb6-91" aria-hidden="true"></a></span>
<span id="cb6-92"><a href="#cb6-92" aria-hidden="true"></a><span class="co"># Send notifications</span></span>
<span id="cb6-93"><a href="#cb6-93" aria-hidden="true"></a><span class="ex">notify_deployment</span> <span class="st">"success"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-94"><a href="#cb6-94" aria-hidden="true"></a></span>
<span id="cb6-95"><a href="#cb6-95" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Deployment Complete ==="</span></span>
<span id="cb6-96"><a href="#cb6-96" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Active release: </span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-97"><a href="#cb6-97" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Site URL: </span><span class="va">$SITE_URL</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="shared-functions-library">Shared Functions Library</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co"># lib/common.sh - Common utilities</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"</span><span class="va">$LOG_DIR</span><span class="st">/deploy-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d<span class="va">)</span><span class="st">.log"</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a><span class="fu">error()</span> <span class="kw">{</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[ERROR] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="op">&gt;&amp;2</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a>    <span class="ex">notify_deployment</span> <span class="st">"failure"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a><span class="fu">run_hook()</span> <span class="kw">{</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">hook_name=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">hook_script=</span><span class="st">"</span><span class="va">$HOOKS_DIR</span><span class="st">/</span><span class="va">${hook_name}</span><span class="st">.sh"</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$hook_script</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"Running hook: </span><span class="va">$hook_name</span><span class="st">"</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a>        <span class="fu">bash</span> <span class="st">"</span><span class="va">$hook_script</span><span class="st">"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true"></a><span class="fu">notify_deployment()</span> <span class="kw">{</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">status=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">environment=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">release=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true"></a></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true"></a>    <span class="co"># Slack notification</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-n</span> <span class="st">"</span><span class="va">$SLACK_WEBHOOK</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true"></a>        <span class="ex">curl</span> -X POST <span class="st">"</span><span class="va">$SLACK_WEBHOOK</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true"></a>            <span class="ex">-H</span> <span class="st">'Content-Type: application/json'</span> <span class="kw">\</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true"></a>            <span class="ex">-d</span> <span class="st">"{</span><span class="dt">\"</span><span class="st">text</span><span class="dt">\"</span><span class="st">:</span><span class="dt">\"</span><span class="st">Deployment </span><span class="va">$status</span><span class="st">: </span><span class="va">$environment</span><span class="st"> (</span><span class="va">$release</span><span class="st">)</span><span class="dt">\"</span><span class="st">}"</span></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true"></a></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true"></a>    <span class="co"># Email notification</span></span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-n</span> <span class="st">"</span><span class="va">$EMAIL_NOTIFICATIONS</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Deployment </span><span class="va">$status</span><span class="st"> on </span><span class="va">$environment</span><span class="st"> (Release: </span><span class="va">$release</span><span class="st">)"</span> <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true"></a>            <span class="ex">mail</span> -s <span class="st">"WordPress Deployment </span><span class="va">$status</span><span class="st">"</span> <span class="st">"</span><span class="va">$EMAIL_NOTIFICATIONS</span><span class="st">"</span></span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true"></a></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true"></a><span class="fu">cleanup_releases()</span> <span class="kw">{</span></span>
<span id="cb7-45"><a href="#cb7-45" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">release_dir=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb7-46"><a href="#cb7-46" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">keep_count=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb7-47"><a href="#cb7-47" aria-hidden="true"></a></span>
<span id="cb7-48"><a href="#cb7-48" aria-hidden="true"></a>    <span class="bu">cd</span> <span class="st">"</span><span class="va">$release_dir</span><span class="st">"</span></span>
<span id="cb7-49"><a href="#cb7-49" aria-hidden="true"></a>    <span class="fu">ls</span> -t <span class="kw">|</span> <span class="fu">tail</span> -n +<span class="va">$((</span>keep_count + 1<span class="va">))</span> <span class="kw">|</span> <span class="fu">xargs</span> rm -rf</span>
<span id="cb7-50"><a href="#cb7-50" aria-hidden="true"></a><span class="kw">}</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="migrations">Database Migration System</h3>



<p>Manage database schema changes safely.</p>



<h4 class="wp-block-heading" id="migration-runner">Migration Runner</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co"># lib/database.sh - Database migration functions</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a><span class="fu">run_migrations()</span> <span class="kw">{</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">release_path=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">migration_dir=</span><span class="st">"</span><span class="va">$MIGRATIONS_DIR</span><span class="st">"</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">applied_file=</span><span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">/.applied-migrations"</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>    <span class="fu">touch</span> <span class="st">"</span><span class="va">$applied_file</span><span class="st">"</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"Checking for pending migrations..."</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true"></a>    <span class="kw">for</span> <span class="ex">migration</span> in <span class="va">$(</span><span class="fu">ls</span> <span class="st">"</span><span class="va">$migration_dir</span><span class="st">"</span>/*.sql <span class="kw">|</span> <span class="fu">sort</span><span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a>        <span class="bu">local</span> <span class="va">migration_name=$(</span><span class="fu">basename</span> <span class="st">"</span><span class="va">$migration</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a>        <span class="co"># Check if already applied</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a>        <span class="kw">if</span> <span class="fu">grep</span> -q <span class="st">"</span><span class="va">$migration_name</span><span class="st">"</span> <span class="st">"</span><span class="va">$applied_file</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true"></a>            <span class="ex">log</span> <span class="st">"  ⊘ Skipping: </span><span class="va">$migration_name</span><span class="st"> (already applied)"</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a>            <span class="bu">continue</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"  → Applying: </span><span class="va">$migration_name</span><span class="st">"</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a>        <span class="co"># Run migration</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a>        <span class="kw">if</span> <span class="ex">wp</span> db query <span class="op">&lt;</span> <span class="st">"</span><span class="va">$migration</span><span class="st">"</span> --path=<span class="st">"</span><span class="va">$release_path</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"</span><span class="va">$migration_name</span><span class="st">"</span> <span class="op">&gt;&gt;</span> <span class="st">"</span><span class="va">$applied_file</span><span class="st">"</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true"></a>            <span class="ex">log</span> <span class="st">"  ✓ Applied: </span><span class="va">$migration_name</span><span class="st">"</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true"></a>        <span class="kw">else</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true"></a>            <span class="ex">error</span> <span class="st">"Migration failed: </span><span class="va">$migration_name</span><span class="st">"</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true"></a></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ All migrations applied"</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true"></a></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true"></a><span class="fu">rollback_migration()</span> <span class="kw">{</span></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">migration_name=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">rollback_file=</span><span class="st">"</span><span class="va">$MIGRATIONS_DIR</span><span class="st">/</span><span class="va">${migration_name%</span>.sql<span class="va">}</span><span class="st">-rollback.sql"</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true"></a></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$rollback_file</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"Rolling back migration: </span><span class="va">$migration_name</span><span class="st">"</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true"></a>        <span class="ex">wp</span> db query <span class="op">&lt;</span> <span class="st">"</span><span class="va">$rollback_file</span><span class="st">"</span></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true"></a>        <span class="ex">error</span> <span class="st">"Rollback file not found: </span><span class="va">$rollback_file</span><span class="st">"</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true"></a><span class="kw">}</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="example-migration-files">Example Migration Files</h4>



<div class="sourceCode" id="cb9">
<pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co">-- migrations/001-add-custom-tables.sql</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> <span class="cf">IF</span> <span class="kw">NOT</span> <span class="kw">EXISTS</span> wp_custom_data (</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a>    <span class="kw">id</span> BIGINT(<span class="dv">20</span>) UNSIGNED <span class="kw">NOT</span> <span class="kw">NULL</span> AUTO_INCREMENT,</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a>    user_id BIGINT(<span class="dv">20</span>) UNSIGNED <span class="kw">NOT</span> <span class="kw">NULL</span>,</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a>    data_key <span class="dt">VARCHAR</span>(<span class="dv">255</span>) <span class="kw">NOT</span> <span class="kw">NULL</span>,</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a>    data_value LONGTEXT,</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a>    created_at DATETIME <span class="kw">DEFAULT</span> <span class="fu">CURRENT_TIMESTAMP</span>,</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a>    <span class="kw">PRIMARY</span> <span class="kw">KEY</span> (<span class="kw">id</span>),</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a>    <span class="kw">KEY</span> user_id (user_id)</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a>) ENGINE<span class="op">=</span>InnoDB <span class="kw">DEFAULT</span> CHARSET<span class="op">=</span>utf8mb4;</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a><span class="co">-- migrations/001-add-custom-tables-rollback.sql</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a><span class="kw">DROP</span> <span class="kw">TABLE</span> <span class="cf">IF</span> <span class="kw">EXISTS</span> wp_custom_data;</span></code></pre>
</div>



<h3 class="wp-block-heading" id="rollback">Rollback System</h3>



<p>Instantly revert failed deployments.</p>



<h4 class="wp-block-heading" id="rollback-script">Rollback Script</h4>



<div class="sourceCode" id="cb10">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a><span class="co"># bin/rollback - Rollback to previous release</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/common.sh"</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>staging<span class="va">}</span><span class="st">"</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a><span class="va">CONFIG_FILE=</span><span class="st">"</span><span class="va">$CONFIG_DIR</span><span class="st">/environments/</span><span class="va">$ENVIRONMENT</span><span class="st">.conf"</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Starting Rollback ==="</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true"></a></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true"></a><span class="co"># Get current release</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true"></a><span class="va">CURRENT=$(</span><span class="fu">readlink</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true"></a><span class="va">CURRENT_NAME=$(</span><span class="fu">basename</span> <span class="st">"</span><span class="va">$CURRENT</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true"></a></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Current release: </span><span class="va">$CURRENT_NAME</span><span class="st">"</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true"></a></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true"></a><span class="co"># Get previous release</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true"></a><span class="va">PREVIOUS=$(</span><span class="fu">ls</span> -t <span class="st">"</span><span class="va">$RELEASE_DIR</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">grep</span> -v <span class="st">"^</span><span class="va">$CURRENT_NAME</span><span class="st"><pre wp-pre-tag-9=""></pre>quot;</span> <span class="kw">|</span> <span class="fu">head</span> -n 1<span class="va">)</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true"></a></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$PREVIOUS</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"No previous release found for rollback"</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true"></a></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true"></a><span class="va">PREVIOUS_PATH=</span><span class="st">"</span><span class="va">$RELEASE_DIR</span><span class="st">/</span><span class="va">$PREVIOUS</span><span class="st">"</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true"></a></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Rolling back to: </span><span class="va">$PREVIOUS</span><span class="st">"</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true"></a></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true"></a><span class="co"># Backup current state (in case rollback fails)</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true"></a><span class="va">ROLLBACK_BACKUP=</span><span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/pre-rollback-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span><span class="st">"</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$ROLLBACK_BACKUP</span><span class="st">"</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"</span><span class="va">$ROLLBACK_BACKUP</span><span class="st">/database.sql.gz"</span> --path=<span class="st">"</span><span class="va">$CURRENT</span><span class="st">"</span></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true"></a></span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true"></a><span class="co"># Switch to previous release</span></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true"></a><span class="fu">ln</span> -nfs <span class="st">"</span><span class="va">$PREVIOUS_PATH</span><span class="st">"</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true"></a></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true"></a></span>
<span id="cb10-45"><a href="#cb10-45" aria-hidden="true"></a><span class="co"># Verify rollback</span></span>
<span id="cb10-46"><a href="#cb10-46" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> core is-installed --path=<span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb10-47"><a href="#cb10-47" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ Rollback successful"</span></span>
<span id="cb10-48"><a href="#cb10-48" aria-hidden="true"></a>    <span class="ex">notify_deployment</span> <span class="st">"rollback-success"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$PREVIOUS</span><span class="st">"</span></span>
<span id="cb10-49"><a href="#cb10-49" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb10-50"><a href="#cb10-50" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Rollback verification failed"</span></span>
<span id="cb10-51"><a href="#cb10-51" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb10-52"><a href="#cb10-52" aria-hidden="true"></a></span>
<span id="cb10-53"><a href="#cb10-53" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Rollback Complete ==="</span></span>
<span id="cb10-54"><a href="#cb10-54" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Active release: </span><span class="va">$PREVIOUS</span><span class="st">"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="monitoring">Health Monitoring System</h3>



<p>Continuous uptime and performance monitoring.</p>



<h4 class="wp-block-heading" id="monitoring-script">Monitoring Script</h4>



<div class="sourceCode" id="cb11">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="co"># bin/monitor - WordPress health monitoring</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/common.sh"</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>production<span class="va">}</span><span class="st">"</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a><span class="va">CONFIG_FILE=</span><span class="st">"</span><span class="va">$CONFIG_DIR</span><span class="st">/environments/</span><span class="va">$ENVIRONMENT</span><span class="st">.conf"</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true"></a></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true"></a><span class="fu">check_site_health()</span> <span class="kw">{</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">url=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">response=$(</span><span class="ex">curl</span> -s -o /dev/null -w <span class="st">"%{http_code}"</span> <span class="st">"</span><span class="va">$url</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true"></a></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$response</span><span class="st">"</span> <span class="ot">=</span> <span class="st">"200"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"✓ Site accessible: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true"></a>        <span class="bu">return</span> 0</span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true"></a>        <span class="ex">error</span> <span class="st">"✗ Site down: </span><span class="va">$url</span><span class="st"> (HTTP </span><span class="va">$response</span><span class="st">)"</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true"></a>        <span class="bu">return</span> 1</span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true"></a></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true"></a><span class="fu">check_database_connection()</span> <span class="kw">{</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> db check --path=<span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"✓ Database connection OK"</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true"></a>        <span class="bu">return</span> 0</span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true"></a>        <span class="ex">error</span> <span class="st">"✗ Database connection failed"</span></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true"></a>        <span class="bu">return</span> 1</span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true"></a></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true"></a><span class="fu">check_disk_space()</span> <span class="kw">{</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">usage=$(</span><span class="fu">df</span> -h <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">awk</span> <span class="st">'NR==2 {print $5}'</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s/%//'</span><span class="va">)</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true"></a></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$usage</span><span class="st">"</span> <span class="ot">-lt</span> 80<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"✓ Disk space OK (</span><span class="va">$usage</span><span class="st">%)"</span></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true"></a>        <span class="bu">return</span> 0</span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"⚠ Disk space warning: </span><span class="va">$usage</span><span class="st">%"</span></span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true"></a>        <span class="bu">return</span> 1</span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true"></a></span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true"></a><span class="fu">check_plugin_updates()</span> <span class="kw">{</span></span>
<span id="cb11-49"><a href="#cb11-49" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">updates=$(</span><span class="ex">wp</span> plugin list --update=available --format=count --path=<span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb11-50"><a href="#cb11-50" aria-hidden="true"></a></span>
<span id="cb11-51"><a href="#cb11-51" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$updates</span><span class="st">"</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-52"><a href="#cb11-52" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"✓ All plugins up to date"</span></span>
<span id="cb11-53"><a href="#cb11-53" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-54"><a href="#cb11-54" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"⚠ </span><span class="va">$updates</span><span class="st"> plugin updates available"</span></span>
<span id="cb11-55"><a href="#cb11-55" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-56"><a href="#cb11-56" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-57"><a href="#cb11-57" aria-hidden="true"></a></span>
<span id="cb11-58"><a href="#cb11-58" aria-hidden="true"></a><span class="co"># Run all checks</span></span>
<span id="cb11-59"><a href="#cb11-59" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Health Check: </span><span class="va">$ENVIRONMENT</span><span class="st"> ==="</span></span>
<span id="cb11-60"><a href="#cb11-60" aria-hidden="true"></a></span>
<span id="cb11-61"><a href="#cb11-61" aria-hidden="true"></a><span class="va">FAILED=</span>0</span>
<span id="cb11-62"><a href="#cb11-62" aria-hidden="true"></a></span>
<span id="cb11-63"><a href="#cb11-63" aria-hidden="true"></a><span class="ex">check_site_health</span> <span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span> <span class="kw">||</span> <span class="va">FAILED=$((</span>FAILED + 1<span class="va">))</span></span>
<span id="cb11-64"><a href="#cb11-64" aria-hidden="true"></a><span class="ex">check_database_connection</span> <span class="kw">||</span> <span class="va">FAILED=$((</span>FAILED + 1<span class="va">))</span></span>
<span id="cb11-65"><a href="#cb11-65" aria-hidden="true"></a><span class="ex">check_disk_space</span> <span class="kw">||</span> <span class="va">FAILED=$((</span>FAILED + 1<span class="va">))</span></span>
<span id="cb11-66"><a href="#cb11-66" aria-hidden="true"></a><span class="ex">check_plugin_updates</span></span>
<span id="cb11-67"><a href="#cb11-67" aria-hidden="true"></a></span>
<span id="cb11-68"><a href="#cb11-68" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$FAILED</span><span class="st">"</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-69"><a href="#cb11-69" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"</span><span class="va">$FAILED</span><span class="st"> health checks failed"</span></span>
<span id="cb11-70"><a href="#cb11-70" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb11-71"><a href="#cb11-71" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ All health checks passed"</span></span>
<span id="cb11-72"><a href="#cb11-72" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="scheduled-monitoring">Scheduled Monitoring</h4>



<div class="sourceCode" id="cb12">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a><span class="co"># Add to crontab: crontab -e</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a><span class="co"># Health check every 5 minutes</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a><span class="ex">*/5</span> * * * * /opt/wordpress-deploy/bin/monitor production <span class="op">&gt;&gt;</span> /var/log/wp-monitor.log <span class="op">2&gt;&amp;1</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true"></a><span class="co"># Daily deployment report</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a><span class="ex">0</span> 9 * * * /opt/wordpress-deploy/bin/report production <span class="kw">|</span> <span class="ex">mail</span> -s <span class="st">"Daily WordPress Report"</span> team@example.com</span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have a complete production-ready WordPress deployment system.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: System setup</p>



<ul class="wp-block-list">
<li>Install deployment system</li>



<li>Configure environments</li>



<li>Test provisioning</li>
</ul>



<p><strong>Week 2</strong>: Deployment workflow</p>



<ul class="wp-block-list">
<li>Practice deployments</li>



<li>Test rollback procedures</li>



<li>Configure notifications</li>
</ul>



<p><strong>Week 3</strong>: CI/CD integration</p>



<ul class="wp-block-list">
<li>Connect to GitHub Actions</li>



<li>Automate testing</li>



<li>Deploy on merge</li>
</ul>



<p><strong>Week 4</strong>: Production hardening</p>



<ul class="wp-block-list">
<li>Implement monitoring</li>



<li>Optimize performance</li>



<li>Document procedures</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Multi-Server Deployments</a></strong> &#8211; Load-balanced WordPress</li>



<li><strong><a href="#">Container-Based Deployments</a></strong> &#8211; Docker/Kubernetes</li>



<li><strong><a href="#">GitOps Workflows</a></strong> &#8211; Infrastructure as code</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download complete system</a></strong> including:</p>



<ul class="wp-block-list">
<li>Full deployment scripts</li>



<li>Configuration templates</li>



<li>Documentation</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>DevOps best practices</li>



<li>Production war stories</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>A complete WordPress deployment system automates the entire lifecycle from server provisioning to zero-downtime deployments, monitoring, and rollback—enabling professional DevOps workflows for WordPress sites.</p>



<p>What we covered:</p>



<p>✅ Complete system architecture and project structure <br>✅ Automated server provisioning from scratch <br>✅ Zero-downtime deployment implementation <br>✅ Database migration system with rollback <br>✅ Instant rollback for failed deployments <br>✅ Continuous health monitoring and alerting</p>



<p>Build this system, and you’ll deploy WordPress professionally—automated provisioning, zero-downtime releases, instant rollbacks, and comprehensive monitoring for production-grade WordPress operations.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">high-availability WordPress</a> or <a href="#">enterprise DevOps</a>.</p>



<p><strong>Questions about WordPress deployment systems?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other DevOps engineers.</p>
<p>The post <a href="https://wpclimastery.com/blog/building-a-complete-wordpress-deployment-system-with-wp-cli-real-project/">Building a Complete WordPress Deployment System with WP-CLI (Real Project)</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WP-CLI Search-Replace: Safe Database Modifications for WordPress Migration</title>
		<link>https://wpclimastery.com/blog/wp-cli-search-replace-safe-database-modifications-for-wordpress-migration/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Sun, 25 Jan 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Advanced WP-CLI Techniques]]></category>
		<category><![CDATA[database search replace]]></category>
		<category><![CDATA[wordpress database migration]]></category>
		<category><![CDATA[wordpress url change]]></category>
		<category><![CDATA[wp-cli db]]></category>
		<category><![CDATA[wp-cli search-replace]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=138</guid>

					<description><![CDATA[<p>Changing URLs in WordPress databases manually destroys serialized data, breaks widget settings, corrupts option values, and leaves your site unusable. MySQL find-replace queries seem simple until you realize WordPress stores...</p>
<p>The post <a href="https://wpclimastery.com/blog/wp-cli-search-replace-safe-database-modifications-for-wordpress-migration/">WP-CLI Search-Replace: Safe Database Modifications for WordPress Migration</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Changing URLs in WordPress databases manually destroys serialized data, breaks widget settings, corrupts option values, and leaves your site unusable. MySQL find-replace queries seem simple until you realize WordPress stores array lengths in serialized strings—one wrong replacement breaks everything.</p>



<p>WP-CLI’s <code>search-replace</code> command handles serialized data automatically, validates replacements before executing, and shows exactly what changed. It’s the only safe way to modify WordPress database content at scale.</p>



<p>In this guide, you’ll master WP-CLI search-replace for site migrations, domain changes, protocol updates, and any database modification requiring precision and safety.</p>



<h3 class="wp-block-heading" id="why-search-replace">Why WP-CLI Search-Replace is Critical</h3>



<p><a href="https://www.php.net/manual/en/function.serialize.php">WordPress serialized data</a> contains length values that break when modified with simple find-replace operations.</p>



<h4 class="wp-block-heading" id="problems-with-manual-database-search-replace">Problems with Manual Database Search-Replace</h4>



<p><strong>Serialized data corruption</strong>: Direct MySQL replacement breaks array and object serialization.</p>



<p><strong>Partial replacements</strong>: URLs in JSON, meta fields, and options get missed.</p>



<p><strong>No validation</strong>: Can’t preview changes before executing them.</p>



<p><strong>No reporting</strong>: Don’t know what was changed or how many replacements occurred.</p>



<p><strong>Irreversible</strong>: Once executed, can’t undo without restoring backups.</p>



<h4 class="wp-block-heading" id="wp-cli-search-replace-advantages">WP-CLI Search-Replace Advantages</h4>



<p><strong>Serialization-safe</strong>: Automatically recalculates lengths in serialized strings.</p>



<p><strong>Dry-run mode</strong>: Preview all changes before executing them.</p>



<p><strong>Comprehensive</strong>: Searches all tables, columns, and data types.</p>



<p><strong>Detailed reporting</strong>: Shows exactly what will change and where.</p>



<p><strong>Table-specific</strong>: Target specific tables or exclude sensitive data.</p>



<p>According to <a href="https://wpengine.com/">WordPress migration studies</a>, 80% of failed migrations are due to incorrect URL replacement breaking serialized data.</p>



<h3 class="wp-block-heading" id="fundamentals">Search-Replace Fundamentals</h3>



<p>Master basic search-replace operations safely.</p>



<h4 class="wp-block-heading" id="basic-search-replace-syntax">Basic Search-Replace Syntax</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="co"># Basic replacement</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old-text'</span> <span class="st">'new-text'</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a><span class="co"># Replace in specific tables</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> wp_posts wp_postmeta</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a><span class="co"># Replace in all tables (dangerous, use carefully)</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --all-tables</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a><span class="co"># Skip specific columns</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --skip-columns=guid</span></code></pre>
</div>



<h4 class="wp-block-heading" id="always-use-dry-run-first">Always Use Dry-Run First</h4>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="co"># Preview changes without executing (CRITICAL!)</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'oldsite.com'</span> <span class="st">'newsite.com'</span> --dry-run</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a><span class="co"># Dry-run with detailed report</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'http://'</span> <span class="st">'https://'</span> --dry-run --report</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a><span class="co"># See exact replacement count</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --dry-run --report --precise</span></code></pre>
</div>



<p><strong>Critical Rule</strong>: NEVER run search-replace without <code>--dry-run</code> first. Always preview changes.</p>



<h4 class="wp-block-heading" id="understanding-serialized-data">Understanding Serialized Data</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co"># WordPress serialized data example:</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># a:3:{s:4:"name";s:4:"John";s:3:"age";i:30;}</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a><span class="co">#      ^ length     ^ length</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a><span class="co"># Direct MySQL replacement breaks this:</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="co"># UPDATE wp_options SET option_value =</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="co"># REPLACE(option_value, 'John', 'Jonathan');</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a><span class="co"># Result: a:3:{s:4:"name";s:8:"Jonathan";...}</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a><span class="co">#                        ^ WRONG! Should be s:8</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a><span class="co"># WP-CLI handles this automatically:</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'John'</span> <span class="st">'Jonathan'</span> wp_options</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a><span class="co"># WP-CLI recalculates: s:4 becomes s:8 automatically</span></span></code></pre>
</div>



<p>Learn more about <a href="https://developer.wordpress.org/cli/commands/search-replace/">WP-CLI search-replace documentation</a>.</p>



<h3 class="wp-block-heading" id="use-cases">Common Search-Replace Use Cases</h3>



<p>Handle the most frequent WordPress database modification scenarios.</p>



<h4 class="wp-block-heading" id="domain-migration">Domain Migration</h4>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="co"># migrate-domain.sh - Complete domain change</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a><span class="va">OLD_DOMAIN=</span><span class="st">"oldsite.com"</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a><span class="va">NEW_DOMAIN=</span><span class="st">"newsite.com"</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a><span class="co"># Backup first (ALWAYS!)</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a><span class="ex">wp</span> db export backup-before-domain-change.sql.gz</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a><span class="co"># Dry-run to preview</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Previewing changes..."</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"https://</span><span class="va">$OLD_DOMAIN</span><span class="st">"</span> <span class="st">"https://</span><span class="va">$NEW_DOMAIN</span><span class="st">"</span> --dry-run --report</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a><span class="co"># Ask for confirmation</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a><span class="bu">read</span> -p <span class="st">"Proceed with replacement? (y/n) "</span> -n 1 -r</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true"></a><span class="bu">echo</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true"></a><span class="kw">if [[</span> <span class="ot">!</span> <span class="va">$REPLY</span> =~ ^[Yy]$<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Operation cancelled"</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true"></a>    <span class="bu">exit</span> 0</span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true"></a></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true"></a><span class="co"># Execute replacements</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Executing replacements..."</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true"></a></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true"></a><span class="co"># Replace full URLs</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"https://</span><span class="va">$OLD_DOMAIN</span><span class="st">"</span> <span class="st">"https://</span><span class="va">$NEW_DOMAIN</span><span class="st">"</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"http://</span><span class="va">$OLD_DOMAIN</span><span class="st">"</span> <span class="st">"https://</span><span class="va">$NEW_DOMAIN</span><span class="st">"</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true"></a></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true"></a><span class="co"># Replace protocol-relative URLs</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"//</span><span class="va">$OLD_DOMAIN</span><span class="st">"</span> <span class="st">"//</span><span class="va">$NEW_DOMAIN</span><span class="st">"</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true"></a></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true"></a><span class="co"># Update WordPress options directly</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"https://</span><span class="va">$NEW_DOMAIN</span><span class="st">"</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"https://</span><span class="va">$NEW_DOMAIN</span><span class="st">"</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true"></a></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true"></a><span class="co"># Flush caches</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true"></a></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Domain migration complete"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="http-to-https-migration">HTTP to HTTPS Migration</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="co"># migrate-to-https.sh</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">DOMAIN=</span><span class="st">"example.com"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a><span class="co"># Backup</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a><span class="ex">wp</span> db export backup-before-https.sql.gz</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a><span class="co"># Dry-run</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"http://</span><span class="va">$DOMAIN</span><span class="st">"</span> <span class="st">"https://</span><span class="va">$DOMAIN</span><span class="st">"</span> --dry-run</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a><span class="co"># Execute</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"http://</span><span class="va">$DOMAIN</span><span class="st">"</span> <span class="st">"https://</span><span class="va">$DOMAIN</span><span class="st">"</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a><span class="co"># Update options</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"https://</span><span class="va">$DOMAIN</span><span class="st">"</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"https://</span><span class="va">$DOMAIN</span><span class="st">"</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Migrated to HTTPS"</span></span></code></pre>
</div>



<p><strong>Use Case</strong>: Essential for SEO and security—Google requires HTTPS for ranking.</p>



<h4 class="wp-block-heading" id="path-changes-subdirectory-moves">Path Changes (Subdirectory Moves)</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co"># Move from subdirectory to root</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'https://example.com/blog'</span> <span class="st">'https://example.com'</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="co"># Move from root to subdirectory</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'https://example.com'</span> <span class="st">'https://example.com/wordpress'</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="co"># Move between subdirectories</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'https://example.com/old'</span> <span class="st">'https://example.com/new'</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="content-text-replacement">Content Text Replacement</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co"># Replace company name in all content</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'Old Company LLC'</span> <span class="st">'New Company Inc'</span> wp_posts</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a><span class="co"># Fix common typos across site</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'recieve'</span> <span class="st">'receive'</span> wp_posts wp_postmeta</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a><span class="co"># Update email addresses</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'contact@oldcompany.com'</span> <span class="st">'contact@newcompany.com'</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a><span class="co"># Replace shortcodes</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'[old_shortcode]'</span> <span class="st">'[new_shortcode]'</span> wp_posts</span></code></pre>
</div>



<h3 class="wp-block-heading" id="advanced-techniques">Advanced Search-Replace Techniques</h3>



<p>Handle complex scenarios with precision.</p>



<h4 class="wp-block-heading" id="regex-pattern-replacement">Regex Pattern Replacement</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co"># Enable regex mode</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'pattern'</span> <span class="st">'replacement'</span> --regex</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a><span class="co"># Replace all HTTP/HTTPS variations</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'https?://oldsite\.com'</span> <span class="st">'https://newsite.com'</span> --regex</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a><span class="co"># Remove URL parameters</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'\?utm_[^\s"]+'</span> <span class="st">''</span> --regex wp_posts</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a><span class="co"># Fix malformed URLs</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'http://http://'</span> <span class="st">'http://'</span> --regex</span></code></pre>
</div>



<p><strong>Warning</strong>: Test regex patterns thoroughly with <code>--dry-run</code>. Incorrect patterns cause unexpected replacements.</p>



<h4 class="wp-block-heading" id="table-specific-operations">Table-Specific Operations</h4>



<div class="sourceCode" id="cb9">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co"># Replace in posts and metadata only</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> wp_posts wp_postmeta</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a><span class="co"># Replace in all tables except options</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --all-tables-with-prefix --skip-tables=wp_options</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a><span class="co"># List all tables first</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a><span class="ex">wp</span> db tables</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a><span class="co"># Replace in custom tables</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> wp_custom_table</span></code></pre>
</div>



<h4 class="wp-block-heading" id="export-replacement-report">Export Replacement Report</h4>



<div class="sourceCode" id="cb10">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a><span class="co"># Generate CSV report of all changes</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --export=changes.csv</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a><span class="co"># Generate report with dry-run</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --dry-run --report <span class="op">&gt;</span> replacement-report.txt</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a><span class="co"># Count replacements</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a><span class="va">REPLACEMENTS=$(</span><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --dry-run --format=count<span class="va">)</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Will replace </span><span class="va">$REPLACEMENTS</span><span class="st"> occurrences"</span></span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/support/article/database-description/">WordPress database tables</a> structure.</p>



<h4 class="wp-block-heading" id="skip-sensitive-columns">Skip Sensitive Columns</h4>



<div class="sourceCode" id="cb11">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="co"># Don't modify GUIDs (recommended)</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --skip-columns=guid</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a><span class="co"># Skip multiple columns</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --skip-columns=guid,post_date</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a><span class="co"># Skip user passwords and meta</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> wp_users --skip-columns=user_pass</span></code></pre>
</div>



<p><strong>Best Practice</strong>: Always skip <code>guid</code> column—changing GUIDs breaks feed readers and external references.</p>



<h3 class="wp-block-heading" id="safe-migration">Safe Migration Workflow</h3>



<p>Complete migration process with validation and rollback capability.</p>



<h4 class="wp-block-heading" id="complete-migration-script">Complete Migration Script</h4>



<div class="sourceCode" id="cb12">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a><span class="co"># Configuration</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a><span class="va">SOURCE_URL=</span><span class="st">"https://staging.example.com"</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true"></a><span class="va">TARGET_URL=</span><span class="st">"https://example.com"</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a><span class="va">BACKUP_DIR=</span><span class="st">"/backups"</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"/var/log/migration.log"</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true"></a></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true"></a></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== WordPress Migration Started ==="</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true"></a></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true"></a><span class="co"># Validate WordPress</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> core is-installed<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"ERROR: WordPress not installed"</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true"></a></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true"></a><span class="co"># Create backup</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating backup..."</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true"></a><span class="va">BACKUP_FILE=</span><span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/pre-migration-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d-%H%M%S<span class="va">)</span><span class="st">.sql.gz"</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"</span><span class="va">$BACKUP_FILE</span><span class="st">"</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true"></a></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true"></a><span class="va">BACKUP_SIZE=$(</span><span class="fu">stat</span> -c%s <span class="st">"</span><span class="va">$BACKUP_FILE</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$BACKUP_SIZE</span><span class="st">"</span> <span class="ot">-lt</span> 1000<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"ERROR: Backup too small, aborting"</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"✓ Backup created: </span><span class="va">$BACKUP_FILE</span><span class="st">"</span></span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true"></a></span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true"></a><span class="co"># Dry-run validation</span></span>
<span id="cb12-35"><a href="#cb12-35" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Validating replacements..."</span></span>
<span id="cb12-36"><a href="#cb12-36" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$TARGET_URL</span><span class="st">"</span> --dry-run --report <span class="op">&amp;&gt;</span> /dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb12-37"><a href="#cb12-37" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"ERROR: Dry-run failed"</span></span>
<span id="cb12-38"><a href="#cb12-38" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-39"><a href="#cb12-39" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb12-40"><a href="#cb12-40" aria-hidden="true"></a></span>
<span id="cb12-41"><a href="#cb12-41" aria-hidden="true"></a><span class="co"># Count expected replacements</span></span>
<span id="cb12-42"><a href="#cb12-42" aria-hidden="true"></a><span class="va">REPLACEMENTS=$(</span><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$TARGET_URL</span><span class="st">"</span> --dry-run --report <span class="kw">|</span> <span class="fu">grep</span> -c <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="kw">||</span> <span class="fu">true</span><span class="va">)</span></span>
<span id="cb12-43"><a href="#cb12-43" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Found </span><span class="va">$REPLACEMENTS</span><span class="st"> occurrences to replace"</span></span>
<span id="cb12-44"><a href="#cb12-44" aria-hidden="true"></a></span>
<span id="cb12-45"><a href="#cb12-45" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$REPLACEMENTS</span><span class="st">"</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb12-46"><a href="#cb12-46" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"WARNING: No replacements found, check URLs"</span></span>
<span id="cb12-47"><a href="#cb12-47" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb12-48"><a href="#cb12-48" aria-hidden="true"></a></span>
<span id="cb12-49"><a href="#cb12-49" aria-hidden="true"></a><span class="co"># Execute replacement</span></span>
<span id="cb12-50"><a href="#cb12-50" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Executing search-replace..."</span></span>
<span id="cb12-51"><a href="#cb12-51" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$TARGET_URL</span><span class="st">"</span> --report</span>
<span id="cb12-52"><a href="#cb12-52" aria-hidden="true"></a></span>
<span id="cb12-53"><a href="#cb12-53" aria-hidden="true"></a><span class="co"># Also replace without protocol</span></span>
<span id="cb12-54"><a href="#cb12-54" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"//staging.example.com"</span> <span class="st">"//example.com"</span></span>
<span id="cb12-55"><a href="#cb12-55" aria-hidden="true"></a></span>
<span id="cb12-56"><a href="#cb12-56" aria-hidden="true"></a><span class="co"># Update options directly</span></span>
<span id="cb12-57"><a href="#cb12-57" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Updating WordPress options..."</span></span>
<span id="cb12-58"><a href="#cb12-58" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$TARGET_URL</span><span class="st">"</span></span>
<span id="cb12-59"><a href="#cb12-59" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$TARGET_URL</span><span class="st">"</span></span>
<span id="cb12-60"><a href="#cb12-60" aria-hidden="true"></a></span>
<span id="cb12-61"><a href="#cb12-61" aria-hidden="true"></a><span class="co"># Verify replacements</span></span>
<span id="cb12-62"><a href="#cb12-62" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Verifying replacements..."</span></span>
<span id="cb12-63"><a href="#cb12-63" aria-hidden="true"></a><span class="va">REMAINING=$(</span><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$TARGET_URL</span><span class="st">"</span> --dry-run --report <span class="kw">|</span> <span class="fu">grep</span> -c <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="kw">||</span> <span class="fu">true</span><span class="va">)</span></span>
<span id="cb12-64"><a href="#cb12-64" aria-hidden="true"></a></span>
<span id="cb12-65"><a href="#cb12-65" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$REMAINING</span><span class="st">"</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb12-66"><a href="#cb12-66" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"WARNING: </span><span class="va">$REMAINING</span><span class="st"> occurrences still remain"</span></span>
<span id="cb12-67"><a href="#cb12-67" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb12-68"><a href="#cb12-68" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ All occurrences replaced"</span></span>
<span id="cb12-69"><a href="#cb12-69" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb12-70"><a href="#cb12-70" aria-hidden="true"></a></span>
<span id="cb12-71"><a href="#cb12-71" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb12-72"><a href="#cb12-72" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb12-73"><a href="#cb12-73" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb12-74"><a href="#cb12-74" aria-hidden="true"></a></span>
<span id="cb12-75"><a href="#cb12-75" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Migration Complete ==="</span></span>
<span id="cb12-76"><a href="#cb12-76" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Rollback backup: </span><span class="va">$BACKUP_FILE</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="rollback-procedure">Rollback Procedure</h4>



<div class="sourceCode" id="cb13">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true"></a><span class="co"># rollback-migration.sh</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a><span class="va">BACKUP_FILE=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true"></a></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$BACKUP_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;backup-file.sql.gz&gt;"</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true"></a></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$BACKUP_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"ERROR: Backup file not found: </span><span class="va">$BACKUP_FILE</span><span class="st">"</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true"></a></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Rolling back to: </span><span class="va">$BACKUP_FILE</span><span class="st">"</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true"></a><span class="bu">read</span> -p <span class="st">"This will overwrite current database. Continue? (y/n) "</span> -n 1 -r</span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true"></a><span class="bu">echo</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true"></a></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true"></a><span class="kw">if [[</span> <span class="ot">!</span> <span class="va">$REPLY</span> =~ ^[Yy]$<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Rollback cancelled"</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true"></a>    <span class="bu">exit</span> 0</span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true"></a></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true"></a><span class="co"># Restore database</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true"></a><span class="ex">wp</span> db import <span class="st">"</span><span class="va">$BACKUP_FILE</span><span class="st">"</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true"></a></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true"></a><span class="co"># Flush caches</span></span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true"></a></span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Rollback complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="troubleshooting">Troubleshooting Search-Replace</h3>



<p>Fix common search-replace issues.</p>



<h4 class="wp-block-heading" id="urls-not-changing">URLs Not Changing</h4>



<div class="sourceCode" id="cb14">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true"></a><span class="co"># Check current URLs in database</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'oldsite.com'</span> <span class="st">'oldsite.com'</span> --dry-run --report <span class="kw">|</span> <span class="fu">head</span> -20</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true"></a><span class="co"># Try all URL variations</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'http://oldsite.com'</span> <span class="st">'https://newsite.com'</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'https://oldsite.com'</span> <span class="st">'https://newsite.com'</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'http://www.oldsite.com'</span> <span class="st">'https://newsite.com'</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'//oldsite.com'</span> <span class="st">'//newsite.com'</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true"></a></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true"></a><span class="co"># Force update options</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">'https://newsite.com'</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">'https://newsite.com'</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="serialization-errors">Serialization Errors</h4>



<div class="sourceCode" id="cb15">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true"></a><span class="co"># Check for serialization issues</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --precise</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true"></a><span class="co"># Skip problematic tables</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> --skip-tables=wp_options</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true"></a></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true"></a><span class="co"># Replace table by table</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">TABLE</span> in <span class="va">$(</span><span class="ex">wp</span> db tables --format=csv<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Processing: </span><span class="va">$TABLE</span><span class="st">"</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true"></a>    <span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> <span class="st">"</span><span class="va">$TABLE</span><span class="st">"</span> --dry-run</span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true"></a><span class="kw">done</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="performance-issues">Performance Issues</h4>



<div class="sourceCode" id="cb16">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true"></a><span class="co"># Large databases may timeout, increase PHP limits</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true"></a><span class="ex">php</span> -d memory_limit=512M wp search-replace <span class="st">'old'</span> <span class="st">'new'</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true"></a><span class="co"># Process tables individually for very large databases</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> wp_posts</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> wp_postmeta</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">'old'</span> <span class="st">'new'</span> wp_options</span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have professional WordPress search-replace skills for safe database migrations.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: Basic replacements</p>



<ul class="wp-block-list">
<li>Practice dry-run workflows</li>



<li>Test domain changes on staging</li>



<li>Learn serialization concepts</li>
</ul>



<p><strong>Week 2</strong>: Advanced techniques</p>



<ul class="wp-block-list">
<li>Master regex patterns</li>



<li>Handle complex migrations</li>



<li>Build verification scripts</li>
</ul>



<p><strong>Week 3</strong>: Production migrations</p>



<ul class="wp-block-list">
<li>Create complete migration workflows</li>



<li>Implement rollback procedures</li>



<li>Document migration playbooks</li>
</ul>



<p><strong>Week 4</strong>: Automation</p>



<ul class="wp-block-list">
<li>Build migration scripts</li>



<li>Add validation checks</li>



<li>Automate testing</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Multisite Search-Replace</a></strong> &#8211; Network-wide replacements</li>



<li><strong><a href="#">Large Database Migrations</a></strong> &#8211; Handle millions of records</li>



<li><strong><a href="#">Custom Table Migrations</a></strong> &#8211; Plugin-specific data</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download migration scripts</a></strong> including:</p>



<ul class="wp-block-list">
<li>Complete migration automation</li>



<li>Rollback procedures</li>



<li>Validation checklists</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>Migration best practices</li>



<li>Advanced database techniques</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>WP-CLI search-replace is the only safe way to modify WordPress database content, handling serialized data automatically while giving you complete control and visibility.</p>



<p>What we covered:</p>



<p>✅ Search-replace fundamentals with dry-run validation <br>✅ Common use cases (domain changes, HTTPS migration, paths) <br>✅ Advanced techniques (regex, table-specific, reporting) <br>✅ Safe migration workflows with backups and rollback <br>✅ Troubleshooting common search-replace issues</p>



<p>Master these techniques, and you’ll handle WordPress migrations and database modifications with confidence—whether changing domains, updating URLs, or migrating content.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">WordPress database optimization</a> or <a href="#">advanced WP-CLI automation</a>.</p>



<p><strong>Questions about WP-CLI search-replace?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other WordPress developers.</p>
<p>The post <a href="https://wpclimastery.com/blog/wp-cli-search-replace-safe-database-modifications-for-wordpress-migration/">WP-CLI Search-Replace: Safe Database Modifications for WordPress Migration</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WordPress CI/CD Pipeline with GitHub Actions and WP-CLI</title>
		<link>https://wpclimastery.com/blog/wordpress-ci-cd-pipeline-with-github-actions-and-wp-cli/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Tue, 20 Jan 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[WordPress DevOps]]></category>
		<category><![CDATA[continuous integration wordpress]]></category>
		<category><![CDATA[github actions wordpress]]></category>
		<category><![CDATA[wordpress ci cd]]></category>
		<category><![CDATA[wordpress deployment automation]]></category>
		<category><![CDATA[wp-cli devops]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=15</guid>

					<description><![CDATA[<p>Manually deploying WordPress changes is risky, time-consuming, and prone to human error. Push to FTP, run SQL updates, clear caches, pray nothing breaks. When something goes wrong at 2 AM,...</p>
<p>The post <a href="https://wpclimastery.com/blog/wordpress-ci-cd-pipeline-with-github-actions-and-wp-cli/">WordPress CI/CD Pipeline with GitHub Actions and WP-CLI</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Manually deploying WordPress changes is risky, time-consuming, and prone to human error. Push to FTP, run SQL updates, clear caches, pray nothing breaks. When something goes wrong at 2 AM, there&#8217;s no easy rollback.</p>



<p>Professional WordPress development requires automated CI/CD (Continuous Integration/Continuous Deployment) pipelines that test, build, and deploy code safely and consistently.</p>



<p>In this advanced guide, you&#8217;ll learn to build a production-ready WordPress CI/CD pipeline using GitHub Actions and WP-CLI. You&#8217;ll implement automated testing, staging deployments, database migrations, and zero-downtime production deployments—all triggered automatically by Git pushes.</p>



<p>By the end, you&#8217;ll have a professional WordPress DevOps workflow that eliminates deployment fear.</p>



<h3 class="wp-block-heading" id="what-is-cicd-for-wordpress-what-is-cicd">What is CI/CD for WordPress?</h3>



<h4 class="wp-block-heading" id="cicd-defined">CI/CD Defined</h4>



<p><strong>Continuous Integration (CI):</strong></p>



<ul class="wp-block-list">
<li>Automatically test code changes</li>



<li>Verify WordPress functionality</li>



<li>Run security checks</li>



<li>Ensure code quality</li>
</ul>



<p><strong>Continuous Deployment (CD):</strong></p>



<ul class="wp-block-list">
<li>Automatically deploy to staging</li>



<li>Deploy to production on approval</li>



<li>Run database migrations</li>



<li>Zero-downtime deployments</li>
</ul>



<h4 class="wp-block-heading" id="the-manual-deployment-problem">The Manual Deployment Problem</h4>



<p><strong>Traditional workflow:</strong></p>



<ol class="wp-block-list">
<li>Make changes locally</li>



<li>FTP files to server (hope you don&#8217;t overwrite something)</li>



<li>SSH and run SQL updates manually</li>



<li>Clear caches</li>



<li>Hope nothing is broken</li>



<li>If broken, scramble to fix or revert</li>
</ol>



<p><strong>Problems:</strong></p>



<ul class="wp-block-list">
<li>Downtime during deployment</li>



<li>Human error (forgot to run migration, uploaded wrong file)</li>



<li>No testing before production</li>



<li>Difficult rollback</li>



<li>No audit trail</li>
</ul>



<h4 class="wp-block-heading" id="cicd-workflow">CI/CD Workflow</h4>



<p><strong>Automated workflow:</strong></p>



<ol class="wp-block-list">
<li>Push code to GitHub</li>



<li><strong>CI</strong>: Automated tests run</li>



<li><strong>CD</strong>: Deploy to staging automatically</li>



<li>QA tests staging environment</li>



<li>Approve production deployment</li>



<li><strong>CD</strong>: Deploy to production with zero downtime</li>



<li>Automatic rollback if issues detected</li>
</ol>



<p><strong>Benefits:</strong></p>



<ul class="wp-block-list">
<li>No manual deployment steps</li>



<li>Every deployment is tested</li>



<li>Instant rollback capability</li>



<li>Complete audit trail in Git</li>



<li>Confidence to deploy frequently</li>
</ul>



<h3 class="wp-block-heading" id="prerequisites-prerequisites">Prerequisites</h3>



<p>Before building your CI/CD pipeline:</p>



<h4 class="wp-block-heading" id="required-accounts">Required Accounts</h4>



<ul class="wp-block-list">
<li><strong>GitHub Account</strong>&nbsp;&#8211; For repository and Actions</li>



<li><strong>WordPress Server(s)</strong>&nbsp;&#8211; Staging and production with SSH access</li>



<li><strong>WP-CLI Access</strong>&nbsp;&#8211; On all WordPress servers</li>
</ul>



<h4 class="wp-block-heading" id="server-requirements">Server Requirements</h4>



<p><strong>Both staging and production need:</strong></p>



<ul class="wp-block-list">
<li>SSH access</li>



<li>WP-CLI installed &#8211; <a href="#">Installation guide</a></li>



<li>Git installed</li>



<li>Web server (Apache/Nginx)</li>



<li>MySQL/MariaDB database</li>
</ul>



<h4 class="wp-block-heading" id="local-development">Local Development</h4>



<ul class="wp-block-list">
<li>Git installed</li>



<li>Basic understanding of WordPress development</li>



<li><a href="#">Bash scripting knowledge</a></li>
</ul>



<h4 class="wp-block-heading" id="knowledge-requirements">Knowledge Requirements</h4>



<p>Helpful background:</p>



<ul class="wp-block-list">
<li>Git basics (branches, commits, pull requests)</li>



<li>GitHub fundamentals</li>



<li>WordPress theme/plugin development</li>



<li>SSH and server administration</li>
</ul>



<h3 class="wp-block-heading" id="github-actions-basics-github-actions-basics">GitHub Actions Basics</h3>



<h4 class="wp-block-heading" id="what-are-github-actions">What are GitHub Actions?</h4>



<p>GitHub Actions are automated workflows that run when specific GitHub events occur (push, pull request, release, etc.).</p>



<p><strong>Workflow anatomy:</strong></p>



<pre class="wp-block-code"><code>name: WordPress CI/CD

on:
  push:
    branches: &#91;main, develop]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run tests
        run: ./run-tests.sh
</code></pre>



<p><strong>Key concepts:</strong></p>



<ul class="wp-block-list">
<li><strong>Workflow</strong>: YAML file defining automation</li>



<li><strong>Event</strong>: Trigger (push, pull_request, schedule)</li>



<li><strong>Job</strong>: Set of steps that run on a runner</li>



<li><strong>Step</strong>: Individual task (run command, use action)</li>



<li><strong>Runner</strong>: Server that runs workflows (GitHub-hosted or self-hosted)</li>
</ul>



<h4 class="wp-block-heading" id="why-github-actions-for-wordpress">Why GitHub Actions for WordPress?</h4>



<p><strong>Advantages:</strong></p>



<ul class="wp-block-list">
<li>Free for public repos (2,000 minutes/month for private)</li>



<li>Integrated with GitHub (no external CI service)</li>



<li>Large marketplace of pre-built actions</li>



<li>Supports matrix builds (test multiple PHP versions)</li>



<li>Secret management built-in</li>
</ul>



<p>Learn more:&nbsp;<a href="https://docs.github.com/en/actions">GitHub Actions Documentation</a></p>



<h3 class="wp-block-heading" id="setting-up-your-repository-repository-setup">Setting Up Your Repository</h3>



<h4 class="wp-block-heading" id="repository-structure">Repository Structure</h4>



<p>Organize your WordPress project for CI/CD:</p>



<pre class="wp-block-code"><code>wordpress-project/
├── .github/
│   └── workflows/
│       ├── ci.yml           # Continuous Integration
│       └── deploy.yml       # Continuous Deployment
├── wp-content/
│   ├── themes/
│   │   └── my-theme/
│   ├── plugins/
│   │   └── my-plugin/
│   └── mu-plugins/
├── scripts/
│   ├── deploy.sh            # Deployment script
│   ├── test.sh              # Testing script
│   └── migrate.sh           # Database migration
├── tests/
│   └── test-wordpress.php
├── composer.json
└── README.md
</code></pre>



<p><strong>What to version control:</strong></p>



<ul class="wp-block-list">
<li>✅ Custom themes</li>



<li>✅ Custom plugins</li>



<li>✅ mu-plugins</li>



<li>✅ Configuration files</li>



<li>✅ Deployment scripts</li>
</ul>



<p><strong>What NOT to version:</strong></p>



<ul class="wp-block-list">
<li>❌ WordPress core (use Composer or WP-CLI)</li>



<li>❌ Third-party plugins (manage separately)</li>



<li>❌&nbsp;<code>wp-config.php</code>&nbsp;(use environment-specific configs)</li>



<li>❌&nbsp;<code>uploads/</code>&nbsp;directory</li>



<li>❌&nbsp;<code>.env</code>&nbsp;files with secrets</li>
</ul>



<h4 class="wp-block-heading" id="create-gitignore">Create .gitignore</h4>



<pre class="wp-block-code"><code><em># .gitignore for WordPress</em>

<em># WordPress core</em>
/wp-admin/
/wp-includes/
/wp-*.php
/xmlrpc.php
/license.txt
/readme.html

<em># Configuration</em>
wp-config.php
.env
.env.*

<em># Uploads</em>
wp-content/uploads/

<em># Cache</em>
wp-content/cache/
wp-content/backup*/

<em># Third-party plugins (manage via Composer)</em>
wp-content/plugins/*
!wp-content/plugins/my-custom-plugin/

<em># IDE</em>
.vscode/
.idea/

<em># OS</em>
.DS_Store
Thumbs.db

<em># Dependencies</em>
/vendor/
node_modules/
</code></pre>



<h4 class="wp-block-heading" id="initialize-repository">Initialize Repository</h4>



<pre class="wp-block-code"><code><em># Create repository</em>
git init
git add .
git commit -m "Initial commit"

<em># Create and push to GitHub</em>
gh repo create my-wordpress-site --public --source=. --remote=origin --push

<em># Or manually</em>
git remote add origin git@github.com:username/my-wordpress-site.git
git push -u origin main
</code></pre>



<h3 class="wp-block-heading" id="wordpress-testing-environment-testing-environment">WordPress Testing Environment</h3>



<h4 class="wp-block-heading" id="set-up-wordpress-in-github-actions">Set Up WordPress in GitHub Actions</h4>



<p>Use the&nbsp;<code>setup-wordpress</code>&nbsp;action to create a test environment:</p>



<pre class="wp-block-code"><code><em># .github/workflows/ci.yml</em>

name: WordPress CI

on:
  push:
    branches: &#91;main, develop]
  pull_request:
    branches: &#91;main]

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: wordpress_test
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

    steps:
      - uses: actions/checkout@v3

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.1'
          extensions: mysql, mbstring, xml
          tools: wp-cli

      - name: Install WordPress
        run: |
          wp core download --path=/tmp/wordpress
          wp config create --dbname=wordpress_test --dbuser=root --dbpass=root --dbhost=127.0.0.1 --path=/tmp/wordpress
          wp core install --url=http://localhost --title="Test Site" --admin_user=admin --admin_password=admin --admin_email=admin@test.com --path=/tmp/wordpress

      - name: Activate plugin/theme
        run: |
          # Copy your custom code
          cp -r $GITHUB_WORKSPACE/wp-content/plugins/my-plugin /tmp/wordpress/wp-content/plugins/
          wp plugin activate my-plugin --path=/tmp/wordpress

      - name: Run tests
        run: |
          ./scripts/test.sh
</code></pre>



<h4 class="wp-block-heading" id="create-test-script">Create Test Script</h4>



<pre class="wp-block-code"><code>#!/bin/bash
<em># scripts/test.sh</em>

set -e

WP_PATH="/tmp/wordpress"

echo "Running WordPress tests..."

<em># Test 1: WordPress is installed</em>
wp core is-installed --path=$WP_PATH

<em># Test 2: Database is accessible</em>
wp db check --path=$WP_PATH

<em># Test 3: Plugin is active</em>
wp plugin is-active my-plugin --path=$WP_PATH

<em># Test 4: WordPress version</em>
version=$(wp core version --path=$WP_PATH)
echo "WordPress version: $version"

<em># Test 5: Run PHP CodeSniffer (if configured)</em>
if command -v phpcs &amp;&gt; /dev/null; then
    phpcs --standard=WordPress wp-content/plugins/my-plugin/
fi

echo "✓ All tests passed!"
</code></pre>



<p>Make it executable:</p>



<pre class="wp-block-code"><code>chmod +x scripts/test.sh
git add scripts/test.sh
git commit -m "Add test script"
</code></pre>



<h3 class="wp-block-heading" id="automated-testing-with-wp-cli-automated-testing">Automated Testing with WP-CLI</h3>



<h4 class="wp-block-heading" id="test-categories">Test Categories</h4>



<p><strong>1. Sanity Tests</strong></p>



<ul class="wp-block-list">
<li>WordPress is installed</li>



<li>Database connection works</li>



<li>Required plugins are active</li>
</ul>



<p><strong>2. Functionality Tests</strong></p>



<ul class="wp-block-list">
<li>Custom plugin functions work</li>



<li>Theme renders correctly</li>



<li>Custom post types exist</li>
</ul>



<p><strong>3. Security Tests</strong></p>



<ul class="wp-block-list">
<li>No vulnerable plugins</li>



<li>WordPress core integrity</li>



<li>File permissions</li>
</ul>



<p><strong>4. Performance Tests</strong></p>



<ul class="wp-block-list">
<li>Database query count</li>



<li>Page load time</li>



<li>Cache functionality</li>
</ul>



<h4 class="wp-block-heading" id="comprehensive-test-script">Comprehensive Test Script</h4>



<pre class="wp-block-code"><code>#!/bin/bash
<em># scripts/test.sh - Comprehensive WordPress testing</em>

set -e

WP_PATH=${WP_PATH:-/tmp/wordpress}
RED='\033&#91;0;31m'
GREEN='\033&#91;0;32m'
NC='\033&#91;0m'

test_count=0
passed=0
failed=0

run_test() {
    local test_name=$1
    local test_command=$2

    ((test_count++))
    echo -n "Test $test_count: $test_name... "

    if eval "$test_command" &amp;&gt;/dev/null; then
        echo -e "${GREEN}PASS${NC}"
        ((passed++))
        return 0
    else
        echo -e "${RED}FAIL${NC}"
        ((failed++))
        return 1
    fi
}

echo "========================================="
echo "WordPress Automated Testing"
echo "========================================="

<em># Sanity tests</em>
run_test "WordPress installed" "wp core is-installed --path=$WP_PATH"
run_test "Database accessible" "wp db check --path=$WP_PATH"
run_test "Core files verified" "wp core verify-checksums --path=$WP_PATH"

<em># Plugin tests</em>
run_test "Custom plugin active" "wp plugin is-active my-plugin --path=$WP_PATH"
run_test "No plugin errors" "wp plugin list --path=$WP_PATH --status=active --format=count"

<em># Theme tests</em>
run_test "Theme activated" "wp theme is-active my-theme --path=$WP_PATH"

<em># Security tests</em>
run_test "No vulnerable plugins" "! wp plugin list --path=$WP_PATH --field=update | grep -q available"

<em># Performance tests</em>
run_test "Cache object working" "wp cache flush --path=$WP_PATH"

<em># Database tests</em>
run_test "Database optimized" "wp db optimize --path=$WP_PATH"

echo "========================================="
echo "Test Results: $passed passed, $failed failed"
echo "========================================="

if &#91; $failed -gt 0 ]; then
    exit 1
fi

exit 0
</code></pre>



<h4 class="wp-block-heading" id="matrix-testing-multiple-php-versions">Matrix Testing (Multiple PHP Versions)</h4>



<pre class="wp-block-code"><code>jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php-version: &#91;'7.4', '8.0', '8.1']
        wordpress-version: &#91;'6.2', '6.3', '6.4']

    name: PHP ${{ matrix.php-version }} / WP ${{ matrix.wordpress-version }}

    steps:
      - uses: actions/checkout@v3

      - name: Setup PHP ${{ matrix.php-version }}
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php-version }}

      - name: Install WordPress ${{ matrix.wordpress-version }}
        run: |
          wp core download --version=${{ matrix.wordpress-version }} --path=/tmp/wordpress
          # ... rest of setup

      - name: Run tests
        run: ./scripts/test.sh
</code></pre>



<p>This tests across 9 combinations (3 PHP × 3 WP versions).</p>



<h3 class="wp-block-heading" id="building-the-deployment-workflow-deployment-workflow">Building the Deployment Workflow</h3>



<h4 class="wp-block-heading" id="deployment-script-structure">Deployment Script Structure</h4>



<pre class="wp-block-code"><code>#!/bin/bash
<em># scripts/deploy.sh</em>

set -euo pipefail

ENVIRONMENT=$1  <em># staging or production</em>
SERVER=$2       <em># server hostname</em>
WP_PATH=$3      <em># WordPress path on server</em>

echo "Deploying to $ENVIRONMENT ($SERVER)"

<em># 1. Create backup</em>
ssh $SERVER "cd $WP_PATH &amp;&amp; wp db export backup-$(date +%s).sql"

<em># 2. Pull latest code</em>
ssh $SERVER "cd $WP_PATH &amp;&amp; git pull origin main"

<em># 3. Install dependencies</em>
ssh $SERVER "cd $WP_PATH &amp;&amp; composer install --no-dev"

<em># 4. Run database migrations</em>
ssh $SERVER "cd $WP_PATH &amp;&amp; wp cli migrate"

<em># 5. Clear caches</em>
ssh $SERVER "cd $WP_PATH &amp;&amp; wp cache flush"
ssh $SERVER "cd $WP_PATH &amp;&amp; wp rewrite flush"

<em># 6. Verify deployment</em>
ssh $SERVER "cd $WP_PATH &amp;&amp; wp core is-installed"

echo "✓ Deployment complete!"
</code></pre>



<h4 class="wp-block-heading" id="ssh-key-setup">SSH Key Setup</h4>



<p>Add SSH private key to GitHub Secrets:</p>



<ol class="wp-block-list">
<li>Generate SSH key (if needed):</li>
</ol>



<pre class="wp-block-code"><code>ssh-keygen -t ed25519 -C "github-actions@example.com" -f ~/.ssh/github-actions
</code></pre>



<ol start="2" class="wp-block-list">
<li>Add public key to server:</li>
</ol>



<pre class="wp-block-code"><code>ssh-copy-id -i ~/.ssh/github-actions.pub user@your-server.com
</code></pre>



<ol start="3" class="wp-block-list">
<li>Add private key to GitHub:
<ul class="wp-block-list">
<li>Go to repo Settings → Secrets → Actions</li>



<li>New repository secret</li>



<li>Name:&nbsp;<code>SSH_PRIVATE_KEY</code></li>



<li>Value: Contents of&nbsp;<code>~/.ssh/github-actions</code>&nbsp;(private key)</li>
</ul>
</li>
</ol>



<h3 class="wp-block-heading" id="environment-secrets-management-secrets-management">Environment Secrets Management</h3>



<h4 class="wp-block-heading" id="github-secrets">GitHub Secrets</h4>



<p>Store sensitive data in GitHub Secrets:</p>



<p><strong>Required secrets:</strong></p>



<ul class="wp-block-list">
<li><code>SSH_PRIVATE_KEY</code>&nbsp;&#8211; SSH key for server access</li>



<li><code>SSH_HOST_STAGING</code>&nbsp;&#8211; Staging server hostname</li>



<li><code>SSH_HOST_PRODUCTION</code>&nbsp;&#8211; Production server hostname</li>



<li><code>SSH_USER</code>&nbsp;&#8211; SSH username</li>



<li><code>WP_PATH_STAGING</code>&nbsp;&#8211; WordPress path on staging</li>



<li><code>WP_PATH_PRODUCTION</code>&nbsp;&#8211; WordPress path on production</li>
</ul>



<h4 class="wp-block-heading" id="using-secrets-in-workflows">Using Secrets in Workflows</h4>



<pre class="wp-block-code"><code>jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.7.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Deploy to staging
        run: |
          ./scripts/deploy.sh \
            staging \
            ${{ secrets.SSH_HOST_STAGING }} \
            ${{ secrets.WP_PATH_STAGING }}
</code></pre>



<h4 class="wp-block-heading" id="environment-variables">Environment Variables</h4>



<p>Create environment-specific configurations:</p>



<pre class="wp-block-code"><code>jobs:
  deploy-staging:
    environment: staging
    env:
      WP_ENV: staging
      SSH_HOST: ${{ secrets.SSH_HOST_STAGING }}
      WP_PATH: ${{ secrets.WP_PATH_STAGING }}

  deploy-production:
    environment: production
    env:
      WP_ENV: production
      SSH_HOST: ${{ secrets.SSH_HOST_PRODUCTION }}
      WP_PATH: ${{ secrets.WP_PATH_PRODUCTION }}
</code></pre>



<h3 class="wp-block-heading" id="staging-deployment-staging-deployment">Staging Deployment</h3>



<h4 class="wp-block-heading" id="auto-deploy-to-staging">Auto-Deploy to Staging</h4>



<p>Deploy automatically on push to&nbsp;<code>develop</code>&nbsp;branch:</p>



<pre class="wp-block-code"><code><em># .github/workflows/deploy-staging.yml</em>

name: Deploy to Staging

on:
  push:
    branches: &#91;develop]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: staging

    steps:
      - uses: actions/checkout@v3

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.7.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Deploy to staging server
        run: |
          ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST_STAGING }} &lt;&lt; 'ENDSSH'
            set -e
            cd ${{ secrets.WP_PATH_STAGING }}

            <em># Backup database</em>
            wp db export backup-$(date +%Y%m%d-%H%M%S).sql

            <em># Pull latest code</em>
            git fetch origin
            git reset --hard origin/develop

            <em># Install dependencies</em>
            composer install --no-dev --optimize-autoloader

            <em># Database migrations</em>
            if &#91; -f scripts/migrate.sh ]; then
              ./scripts/migrate.sh
            fi

            <em># Clear caches</em>
            wp cache flush
            wp rewrite flush

            <em># Verify</em>
            wp core is-installed &amp;&amp; echo "Deployment successful!"
          ENDSSH

      - name: Notify on Slack
        if: always()
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          text: 'Staging deployment: ${{ job.status }}'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}
</code></pre>



<h3 class="wp-block-heading" id="production-deployment-production-deployment">Production Deployment</h3>



<h4 class="wp-block-heading" id="manual-approval-required">Manual Approval Required</h4>



<p>Require manual approval before production deployment:</p>



<pre class="wp-block-code"><code><em># .github/workflows/deploy-production.yml</em>

name: Deploy to Production

on:
  workflow_dispatch:  <em># Manual trigger only</em>
  release:
    types: &#91;published]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://yoursite.com

    steps:
      - uses: actions/checkout@v3

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.7.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Pre-deployment checks
        run: |
          # Verify staging is working
          curl -f https://staging.yoursite.com || exit 1

      - name: Create backup
        run: |
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST_PRODUCTION }} \
            "cd ${{ secrets.WP_PATH_PRODUCTION }} &amp;&amp; wp db export backups/pre-deploy-$(date +%s).sql"

      - name: Deploy to production
        run: |
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST_PRODUCTION }} &lt;&lt; 'ENDSSH'
            set -e
            cd ${{ secrets.WP_PATH_PRODUCTION }}

            <em># Enable maintenance mode</em>
            wp maintenance-mode activate

            <em># Pull latest code</em>
            git fetch origin
            git reset --hard origin/main

            <em># Install dependencies</em>
            composer install --no-dev --optimize-autoloader

            <em># Database migrations</em>
            if &#91; -f scripts/migrate.sh ]; then
              ./scripts/migrate.sh
            fi

            <em># Clear caches</em>
            wp cache flush
            wp rewrite flush
            wp transient delete --all

            <em># Disable maintenance mode</em>
            wp maintenance-mode deactivate

            <em># Verify</em>
            wp core is-installed &amp;&amp; echo "Production deployment successful!"
          ENDSSH

      - name: Smoke tests
        run: |
          # Test homepage
          curl -f https://yoursite.com

          <em># Test critical pages</em>
          curl -f https://yoursite.com/about
          curl -f https://yoursite.com/contact

      - name: Rollback on failure
        if: failure()
        run: |
          echo "Deployment failed, initiating rollback..."
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST_PRODUCTION }} \
            "cd ${{ secrets.WP_PATH_PRODUCTION }} &amp;&amp; git reset --hard HEAD~1"
</code></pre>



<h4 class="wp-block-heading" id="protected-branches">Protected Branches</h4>



<p>Configure branch protection in GitHub:</p>



<ol class="wp-block-list">
<li>Go to Settings → Branches</li>



<li>Add rule for&nbsp;<code>main</code>&nbsp;branch</li>



<li>Enable:
<ul class="wp-block-list">
<li>Require pull request reviews (1+ approvals)</li>



<li>Require status checks to pass (CI tests)</li>



<li>Require branches to be up to date</li>
</ul>
</li>
</ol>



<p>This ensures production only receives tested, reviewed code.</p>



<h3 class="wp-block-heading" id="database-migrations-database-migrations">Database Migrations</h3>



<h4 class="wp-block-heading" id="migration-script-pattern">Migration Script Pattern</h4>



<pre class="wp-block-code"><code>#!/bin/bash
<em># scripts/migrate.sh</em>

set -e

WP_PATH=${WP_PATH:-.}

echo "Running database migrations..."

<em># Migration 001: Add custom table</em>
wp db query "
  CREATE TABLE IF NOT EXISTS wp_custom_data (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    user_id bigint(20) NOT NULL,
    data longtext NOT NULL,
    created_at datetime NOT NULL,
    PRIMARY KEY (id)
  );
" --path=$WP_PATH

<em># Migration 002: Update post meta</em>
wp post meta update-all custom_field new_value --from=old_value --path=$WP_PATH

<em># Migration 003: Create custom taxonomy</em>
wp taxonomy register custom_taxonomy --path=$WP_PATH

echo "✓ Migrations complete!"
</code></pre>



<h4 class="wp-block-heading" id="version-controlled-migrations">Version-Controlled Migrations</h4>



<p>Use migration files:</p>



<pre class="wp-block-code"><code><em># migrations/001-create-custom-table.sql</em>
CREATE TABLE IF NOT EXISTS wp_custom_data (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  data longtext NOT NULL,
  PRIMARY KEY (id)
);

<em># migrations/002-add-meta-field.sh</em>
<em>#!/bin/bash</em>
wp post list --format=ids | xargs -I {} wp post meta update {} new_field default_value
</code></pre>



<p><strong>Migration runner:</strong></p>



<pre class="wp-block-code"><code>#!/bin/bash
<em># scripts/migrate.sh</em>

WP_PATH=${WP_PATH:-.}
MIGRATIONS_DIR="migrations"

for migration in $MIGRATIONS_DIR/*; do
    echo "Running migration: $(basename $migration)"

    if &#91;&#91; $migration == *.sql ]]; then
        wp db query &lt; $migration --path=$WP_PATH
    elif &#91;&#91; $migration == *.sh ]]; then
        bash $migration
    fi

    echo "✓ Completed: $(basename $migration)"
done
</code></pre>



<h3 class="wp-block-heading" id="rollback-strategy-rollback">Rollback Strategy</h3>



<h4 class="wp-block-heading" id="automated-rollback-on-failure">Automated Rollback on Failure</h4>



<pre class="wp-block-code"><code>- name: Deploy with rollback
  id: deploy
  run: |
    # Get current commit for rollback
    CURRENT_COMMIT=$(ssh $SERVER "cd $WP_PATH &amp;&amp; git rev-parse HEAD")
    echo "current_commit=$CURRENT_COMMIT" &gt;&gt; $GITHUB_OUTPUT

    <em># Deploy</em>
    ./scripts/deploy.sh

- name: Verify deployment
  id: verify
  run: |
    # Run smoke tests
    curl -f https://yoursite.com || exit 1
    ssh $SERVER "cd $WP_PATH &amp;&amp; wp core is-installed" || exit 1

- name: Rollback on failure
  if: failure() &amp;&amp; steps.deploy.outcome == 'success'
  run: |
    echo "Deployment verification failed, rolling back..."

    <em># Restore database backup</em>
    BACKUP_FILE=$(ssh $SERVER "ls -t $WP_PATH/backups/*.sql | head -1")
    ssh $SERVER "cd $WP_PATH &amp;&amp; wp db import $BACKUP_FILE"

    <em># Restore code</em>
    ssh $SERVER "cd $WP_PATH &amp;&amp; git reset --hard ${{ steps.deploy.outputs.current_commit }}"

    <em># Clear caches</em>
    ssh $SERVER "cd $WP_PATH &amp;&amp; wp cache flush"

    echo "✓ Rollback complete"
    exit 1
</code></pre>



<h4 class="wp-block-heading" id="manual-rollback-workflow">Manual Rollback Workflow</h4>



<pre class="wp-block-code"><code><em># .github/workflows/rollback.yml</em>

name: Rollback Production

on:
  workflow_dispatch:
    inputs:
      commit_sha:
        description: 'Commit SHA to rollback to'
        required: true

jobs:
  rollback:
    runs-on: ubuntu-latest
    environment: production

    steps:
      - name: Confirm rollback
        run: |
          echo "Rolling back to commit: ${{ github.event.inputs.commit_sha }}"

      - name: Rollback code
        run: |
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST_PRODUCTION }} \
            "cd ${{ secrets.WP_PATH_PRODUCTION }} &amp;&amp; git reset --hard ${{ github.event.inputs.commit_sha }}"

      - name: Restore database
        run: |
          # Restore from backup (manual selection required)
          echo "Please restore database manually from backups/"
</code></pre>



<h3 class="wp-block-heading" id="complete-github-actions-workflow-complete-workflow">Complete GitHub Actions Workflow</h3>



<h4 class="wp-block-heading" id="production-ready-cicd">Production-Ready CI/CD</h4>



<pre class="wp-block-code"><code><em># .github/workflows/wordpress-cicd.yml</em>

name: WordPress CI/CD

on:
  push:
    branches: &#91;main, develop]
  pull_request:
    branches: &#91;main]
  workflow_dispatch:

env:
  PHP_VERSION: '8.1'

jobs:
  <em># Job 1: Run tests</em>
  test:
    name: Test
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: wordpress_test
        ports:
          - 3306:3306

    steps:
      - uses: actions/checkout@v3

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ env.PHP_VERSION }}
          extensions: mysql, mbstring, xml
          tools: wp-cli, composer

      - name: Install WordPress
        run: |
          wp core download --path=/tmp/wordpress
          wp config create \
            --dbname=wordpress_test \
            --dbuser=root \
            --dbpass=root \
            --dbhost=127.0.0.1 \
            --path=/tmp/wordpress
          wp core install \
            --url=http://localhost \
            --title="Test Site" \
            --admin_user=admin \
            --admin_password=admin \
            --admin_email=admin@test.com \
            --path=/tmp/wordpress

      - name: Copy custom code
        run: |
          cp -r wp-content/themes/* /tmp/wordpress/wp-content/themes/
          cp -r wp-content/plugins/* /tmp/wordpress/wp-content/plugins/

      - name: Run tests
        run: ./scripts/test.sh
        env:
          WP_PATH: /tmp/wordpress

  <em># Job 2: Deploy to staging</em>
  deploy-staging:
    name: Deploy to Staging
    needs: test
    if: github.ref == 'refs/heads/develop' &amp;&amp; github.event_name == 'push'
    runs-on: ubuntu-latest
    environment: staging

    steps:
      - uses: actions/checkout@v3

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.7.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Deploy
        run: |
          ./scripts/deploy.sh \
            staging \
            ${{ secrets.SSH_HOST_STAGING }} \
            ${{ secrets.WP_PATH_STAGING }}

  <em># Job 3: Deploy to production</em>
  deploy-production:
    name: Deploy to Production
    needs: test
    if: github.ref == 'refs/heads/main' &amp;&amp; github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://yoursite.com

    steps:
      - uses: actions/checkout@v3

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.7.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Deploy
        id: deploy
        run: |
          ./scripts/deploy.sh \
            production \
            ${{ secrets.SSH_HOST_PRODUCTION }} \
            ${{ secrets.WP_PATH_PRODUCTION }}

      - name: Verify
        run: |
          curl -f https://yoursite.com || exit 1

      - name: Notify
        if: always()
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          text: 'Production deployment: ${{ job.status }}'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}
</code></pre>



<h2 class="wp-block-heading" id="best-practices-best-practices">Best Practices</h2>



<h4 class="wp-block-heading" id="security">Security</h4>



<ol class="wp-block-list">
<li><strong>Never commit secrets</strong>&nbsp;&#8211; Use GitHub Secrets</li>



<li><strong>Restrict SSH access</strong>&nbsp;&#8211; Use dedicated deploy keys</li>



<li><strong>Audit deployments</strong>&nbsp;&#8211; Enable GitHub audit log</li>



<li><strong>Scan for vulnerabilities</strong>&nbsp;&#8211; Use GitHub&#8217;s Dependabot</li>
</ol>



<h4 class="wp-block-heading" id="deployment">Deployment</h4>



<ol class="wp-block-list">
<li><strong>Always test first</strong>&nbsp;&#8211; Run CI tests before deploy</li>



<li><strong>Use staging</strong>&nbsp;&#8211; Test on staging before production</li>



<li><strong>Backup before deploy</strong>&nbsp;&#8211; Automatic database backups</li>



<li><strong>Enable maintenance mode</strong>&nbsp;&#8211; During production deployments</li>



<li><strong>Monitor after deploy</strong>&nbsp;&#8211; Check logs and metrics</li>
</ol>



<h4 class="wp-block-heading" id="code-quality">Code Quality</h4>



<ol class="wp-block-list">
<li><strong>Use linters</strong>&nbsp;&#8211; PHP CodeSniffer, ESLint</li>



<li><strong>Run static analysis</strong>&nbsp;&#8211; PHPStan, Psalm</li>



<li><strong>Code coverage</strong>&nbsp;&#8211; Track test coverage</li>



<li><strong>Peer review</strong>&nbsp;&#8211; Require PR approvals</li>
</ol>



<h4 class="wp-block-heading" id="performance">Performance</h4>



<ol class="wp-block-list">
<li><strong>Cache workflows</strong>&nbsp;&#8211; Cache Composer dependencies</li>



<li><strong>Parallel jobs</strong>&nbsp;&#8211; Run tests in parallel</li>



<li><strong>Self-hosted runners</strong>&nbsp;&#8211; For faster deploys</li>
</ol>



<h3 class="wp-block-heading" id="troubleshooting-troubleshooting">Troubleshooting</h3>



<h4 class="wp-block-heading" id="issue-1-ssh-connection-failed">Issue 1: SSH Connection Failed</h4>



<p><strong>Problem</strong>:&nbsp;<code>Permission denied (publickey)</code></p>



<p><strong>Solutions</strong>:</p>



<ol class="wp-block-list">
<li>Verify SSH key is added to GitHub Secrets correctly</li>



<li>Test SSH connection:</li>
</ol>



<pre class="wp-block-code"><code>ssh -i ~/.ssh/github-actions user@server.com
</code></pre>



<ol start="3" class="wp-block-list">
<li>Check server&#8217;s&nbsp;<code>~/.ssh/authorized_keys</code></li>



<li>Verify SSH agent setup in workflow</li>
</ol>



<h4 class="wp-block-heading" id="issue-2-deployment-timeout">Issue 2: Deployment Timeout</h4>



<p><strong>Problem</strong>: Workflow times out during deployment</p>



<p><strong>Solutions</strong>:</p>



<ol class="wp-block-list">
<li>Increase timeout:</li>
</ol>



<pre class="wp-block-code"><code>jobs:
  deploy:
    timeout-minutes: 30  <em># Default is 360</em>
</code></pre>



<ol start="2" class="wp-block-list">
<li>Optimize deployment script</li>



<li>Use caching for dependencies</li>
</ol>



<h4 class="wp-block-heading" id="issue-3-database-migration-failed">Issue 3: Database Migration Failed</h4>



<p><strong>Problem</strong>: Migration fails, breaks site</p>



<p><strong>Solutions</strong>:</p>



<ol class="wp-block-list">
<li>Always backup before migrations</li>



<li>Test migrations on staging first</li>



<li>Use transactions when possible:</li>
</ol>



<pre class="wp-block-code"><code>START TRANSACTION;
<em>-- migration SQL</em>
COMMIT;
</code></pre>



<ol start="4" class="wp-block-list">
<li>Implement rollback in migration script</li>
</ol>



<h4 class="wp-block-heading" id="issue-4-cache-not-cleared">Issue 4: Cache Not Cleared</h4>



<p><strong>Problem</strong>: Changes don&#8217;t appear after deployment</p>



<p><strong>Solutions</strong>:</p>



<ol class="wp-block-list">
<li>Add cache clearing to deployment:</li>
</ol>



<pre class="wp-block-code"><code>wp cache flush
wp rewrite flush
wp transient delete --all
</code></pre>



<ol start="2" class="wp-block-list">
<li>Clear CDN cache if using one</li>



<li>Verify opcache is reset</li>
</ol>



<h4 class="wp-block-heading" id="issue-5-workflow-fails-silently">Issue 5: Workflow Fails Silently</h4>



<p><strong>Problem</strong>: Workflow completes but deployment didn&#8217;t work</p>



<p><strong>Solutions</strong>:</p>



<ol class="wp-block-list">
<li>Remove&nbsp;<code>set -e</code>&nbsp;temporarily to see errors</li>



<li>Add verbose logging:</li>
</ol>



<pre class="wp-block-code"><code>set -x  <em># Print commands</em>
</code></pre>



<ol start="3" class="wp-block-list">
<li>Check server logs:</li>
</ol>



<pre class="wp-block-code"><code>ssh server "tail -f /var/log/apache2/error.log"
</code></pre>



<h3 class="wp-block-heading" id="next-steps-next-steps">Next Steps</h3>



<p>Congratulations! You&#8217;ve built a production-ready WordPress CI/CD pipeline.</p>



<h4 class="wp-block-heading" id="enhance-your-pipeline">Enhance Your Pipeline</h4>



<ol class="wp-block-list">
<li><strong><a href="https://file+.vscode-resource.vscode-cdn.net/blog/multisite-bulk-operations-wpcli">WordPress Multisite CI/CD</a></strong>&nbsp;&#8211; Deploy to network</li>



<li><strong><a href="https://file+.vscode-resource.vscode-cdn.net/blog/automate-wordpress-backups-wpcli">Automated Backups</a></strong>&nbsp;&#8211; Integrate with deployment</li>



<li><strong><a href="https://file+.vscode-resource.vscode-cdn.net/blog/optimize-wordpress-performance-wpcli">Performance Testing</a></strong>&nbsp;&#8211; Add to CI</li>
</ol>



<h4 class="wp-block-heading" id="related-guides">Related Guides</h4>



<ul class="wp-block-list">
<li><strong><a href="#">Custom WP-CLI Commands</a></strong> &#8211; Build deployment commands</li>



<li><strong><a href="#">Environment Management</a></strong> &#8211; Advanced configs</li>



<li><strong><a href="#">Bash Functions</a></strong> &#8211; Improve scripts</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<p><strong>Add to your pipeline:</strong></p>



<ul class="wp-block-list">
<li>Visual regression testing (BackstopJS, Percy)</li>



<li>Load testing (k6, Apache JBench)</li>



<li>Security scanning (OWASP ZAP)</li>



<li>Accessibility testing (pa11y)</li>



<li>SEO validation</li>



<li>Automated changelogs</li>
</ul>



<h4 class="wp-block-heading" id="master-wordpress-devops">Master WordPress DevOps</h4>



<p>Want to build enterprise-grade WordPress automation?</p>



<p><strong><a href="/#get-started">Join WPCLI Mastery</a></strong> and learn:</p>



<ul class="wp-block-list">
<li>Complete CI/CD pipeline templates</li>



<li>Multi-environment WordPress architecture</li>



<li>Blue-green deployments</li>



<li>Automated rollbacks and disaster recovery</li>



<li>Early bird course pricing ($99 vs $199)</li>
</ul>



<h2 class="wp-block-heading" id="conclusion">Conclusion</h2>



<p>Automated CI/CD pipelines eliminate deployment fear and enable rapid, confident WordPress development. The GitHub Actions workflow you built today provides:</p>



<ul class="wp-block-list">
<li>Automated testing on every push</li>



<li>Safe staging deployments</li>



<li>Controlled production releases</li>



<li>Instant rollback capability</li>



<li>Complete audit trail</li>
</ul>



<p><strong>Key takeaways:</strong></p>



<ul class="wp-block-list">
<li>CI/CD catches errors before production</li>



<li>GitHub Actions integrates seamlessly with WordPress</li>



<li>WP-CLI makes WordPress automation possible</li>



<li>Staging → Production workflow ensures safety</li>



<li>Automated rollbacks prevent disasters</li>



<li>Database migrations need careful handling</li>
</ul>



<p>The CI/CD pipeline you implemented today is the foundation of professional WordPress DevOps. Deploy with confidence.</p>



<p><strong>Ready to implement?</strong>&nbsp;Start with the complete workflow and adapt to your needs.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><strong>Questions about WordPress CI/CD?</strong>&nbsp;Drop a comment below!</p>



<p><strong>Found this helpful?</strong>&nbsp;Share with WordPress developers building automation.</p>



<p><strong>Next:</strong> Explore <a href="#">advanced WordPress deployment strategies</a> and zero-downtime techniques.</p>
<p>The post <a href="https://wpclimastery.com/blog/wordpress-ci-cd-pipeline-with-github-actions-and-wp-cli/">WordPress CI/CD Pipeline with GitHub Actions and WP-CLI</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WordPress Site Cloning and Migration Automation with WP-CLI</title>
		<link>https://wpclimastery.com/blog/wordpress-site-cloning-and-migration-automation-with-wp-cli/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Thu, 15 Jan 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Real-World WP-CLI Projects]]></category>
		<category><![CDATA[automated wordpress migration]]></category>
		<category><![CDATA[clone wordpress site]]></category>
		<category><![CDATA[wordpress migration automation]]></category>
		<category><![CDATA[wordpress site cloning]]></category>
		<category><![CDATA[wp-cli migration]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=143</guid>

					<description><![CDATA[<p>Cloning WordPress sites manually means exporting databases through phpMyAdmin, FTPing thousands of files, running search-replace SQL queries that break serialized data, and spending hours fixing broken configurations. One mistake destroys...</p>
<p>The post <a href="https://wpclimastery.com/blog/wordpress-site-cloning-and-migration-automation-with-wp-cli/">WordPress Site Cloning and Migration Automation with WP-CLI</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Cloning WordPress sites manually means exporting databases through phpMyAdmin, FTPing thousands of files, running search-replace SQL queries that break serialized data, and spending hours fixing broken configurations. One mistake destroys the entire clone.</p>



<p>WP-CLI transforms WordPress cloning and migration into a fast, automated process—clone production to staging in minutes, migrate sites between hosts reliably, and replicate environments for testing without manual intervention or data corruption.</p>



<p>In this guide, you’ll build a complete WordPress site cloning and migration system using WP-CLI, with automated scripts, safety checks, and verification procedures used by professional WordPress agencies.</p>



<h3 class="wp-block-heading" id="why-automate">Why Automate WordPress Cloning and Migration?</h3>



<p><a href="https://wordpress.org/support/article/moving-wordpress/">WordPress site migration</a> manually is error-prone and doesn’t scale.</p>



<h4 class="wp-block-heading" id="problems-with-manual-cloningmigration">Problems with Manual Cloning/Migration</h4>



<p><strong>Time-consuming</strong>: Manual cloning takes 2-4 hours for medium sites.</p>



<p><strong>Error-prone</strong>: Database exports fail, files get missed, URLs break.</p>



<p><strong>Serialized data corruption</strong>: Manual search-replace destroys widget settings and options.</p>



<p><strong>No validation</strong>: Can’t verify clone completeness or data integrity.</p>



<p><strong>Not repeatable</strong>: Each clone requires same tedious manual steps.</p>



<h4 class="wp-block-heading" id="wp-cli-cloningmigration-advantages">WP-CLI Cloning/Migration Advantages</h4>



<p><strong>Fast</strong>: Clone complete sites in 5-10 minutes instead of hours.</p>



<p><strong>Safe</strong>: WordPress-aware operations preserve serialized data.</p>



<p><strong>Scriptable</strong>: One-command cloning for any site at any time.</p>



<p><strong>Verifiable</strong>: Automated checks ensure complete, accurate clones.</p>



<p><strong>Consistent</strong>: Same process every time guarantees reliability.</p>



<p>According to <a href="https://wpengine.com/">WordPress development surveys</a>, agencies save 20+ hours monthly by automating site cloning for staging and development.</p>



<h3 class="wp-block-heading" id="basic-cloning">Basic Site Cloning</h3>



<p>Clone a WordPress site locally with essential components.</p>



<h4 class="wp-block-heading" id="complete-local-clone-script">Complete Local Clone Script</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="co"># clone-wordpress-site.sh - Clone WordPress site locally</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span><span class="bu"> ]</span> <span class="kw">||</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;source_path&gt; &lt;dest_path&gt;"</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Cloning WordPress site..."</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Source: </span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Destination: </span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true"></a></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true"></a><span class="co"># Create destination directory</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true"></a></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true"></a><span class="co"># Copy WordPress files</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Copying files..."</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true"></a><span class="fu">rsync</span> -av --exclude=<span class="st">'wp-content/cache'</span> <span class="kw">\</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-content/backup*'</span> <span class="kw">\</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true"></a>    <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/"</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true"></a></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true"></a><span class="co"># Export database from source</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Exporting database..."</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true"></a><span class="ex">wp</span> db export /tmp/clone-db.sql</span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true"></a></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true"></a><span class="co"># Create new database config for destination</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true"></a></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true"></a><span class="co"># Get source database details</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true"></a><span class="va">SOURCE_DB=$(</span><span class="ex">wp</span> config get DB_NAME<span class="va">)</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true"></a><span class="va">SOURCE_USER=$(</span><span class="ex">wp</span> config get DB_USER<span class="va">)</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true"></a><span class="va">SOURCE_PASS=$(</span><span class="ex">wp</span> config get DB_PASSWORD<span class="va">)</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true"></a></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true"></a><span class="co"># Create new database</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true"></a><span class="va">NEW_DB=</span><span class="st">"cloned_</span><span class="va">${SOURCE_DB}</span><span class="st">"</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true"></a><span class="ex">mysql</span> -u<span class="st">"</span><span class="va">$SOURCE_USER</span><span class="st">"</span> -p<span class="st">"</span><span class="va">$SOURCE_PASS</span><span class="st">"</span> -e <span class="st">"CREATE DATABASE IF NOT EXISTS </span><span class="va">${NEW_DB}</span><span class="st">;"</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true"></a></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true"></a><span class="co"># Update wp-config.php</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true"></a><span class="ex">wp</span> config set DB_NAME <span class="st">"</span><span class="va">$NEW_DB</span><span class="st">"</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true"></a></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true"></a><span class="co"># Import database</span></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Importing database..."</span></span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true"></a><span class="ex">wp</span> db import /tmp/clone-db.sql</span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true"></a></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true"></a><span class="co"># Cleanup</span></span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true"></a><span class="fu">rm</span> /tmp/clone-db.sql</span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true"></a></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true"></a><span class="co"># Update URLs if needed</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true"></a><span class="va">SOURCE_URL=$(</span><span class="ex">wp</span> option get siteurl<span class="va">)</span></span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Current site URL: </span><span class="va">$SOURCE_URL</span><span class="st">"</span></span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true"></a><span class="bu">read</span> -p <span class="st">"Enter new site URL (or press Enter to keep same): "</span> <span class="va">NEW_URL</span></span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true"></a></span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-n</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Updating URLs..."</span></span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true"></a>    <span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true"></a>    <span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb1-63"><a href="#cb1-63" aria-hidden="true"></a>    <span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb1-64"><a href="#cb1-64" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb1-65"><a href="#cb1-65" aria-hidden="true"></a></span>
<span id="cb1-66"><a href="#cb1-66" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb1-67"><a href="#cb1-67" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb1-68"><a href="#cb1-68" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb1-69"><a href="#cb1-69" aria-hidden="true"></a></span>
<span id="cb1-70"><a href="#cb1-70" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Clone complete: </span><span class="va">$DEST_PATH</span><span class="st">"</span></span></code></pre>
</div>



<p>Run it:</p>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="fu">chmod</span> +x clone-wordpress-site.sh</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a><span class="ex">./clone-wordpress-site.sh</span> /var/www/production /var/www/staging</span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/support/article/wordpress-files/">WordPress directory structure</a>.</p>



<h3 class="wp-block-heading" id="remote-migration">Remote Site Migration</h3>



<p>Migrate WordPress sites between servers or hosting providers.</p>



<h4 class="wp-block-heading" id="complete-remote-migration-script">Complete Remote Migration Script</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># migrate-wordpress-remote.sh - Migrate between servers</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="va">SOURCE_HOST=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a><span class="va">OLD_URL=</span><span class="st">"</span><span class="va">$4</span><span class="st">"</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a><span class="va">NEW_URL=</span><span class="st">"</span><span class="va">$5</span><span class="st">"</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;source_host&gt; &lt;source_path&gt; &lt;dest_path&gt; &lt;old_url&gt; &lt;new_url&gt;"</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Example: </span><span class="va">$0</span><span class="st"> user@old-server.com /var/www/html /var/www/html https://oldsite.com https://newsite.com"</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a><span class="va">TEMP_DIR=</span><span class="st">"/tmp/wp-migration-</span><span class="va">$</span><span class="st">"</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a><span class="va">DATE=$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">"</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=== WordPress Remote Migration Started ==="</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"From: </span><span class="va">$SOURCE_HOST</span><span class="st">:</span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"To: </span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"URL: </span><span class="va">$OLD_URL</span><span class="st"> → </span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true"></a></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a><span class="co"># Step 1: Export database from source</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 1/6: Exporting database from source..."</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a><span class="fu">ssh</span> <span class="st">"</span><span class="va">$SOURCE_HOST</span><span class="st">"</span> <span class="st">"cd </span><span class="va">$SOURCE_PATH</span><span class="st"> &amp;&amp; wp db export - | gzip"</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">/database.sql.gz"</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true"></a><span class="co"># Verify database export</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true"></a><span class="va">DB_SIZE=$(</span><span class="fu">stat</span> -c%s <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">/database.sql.gz"</span><span class="va">)</span></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$DB_SIZE</span><span class="st">"</span> <span class="ot">-lt</span> 1000<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Database export too small, aborting"</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true"></a></span>
<span id="cb3-39"><a href="#cb3-39" aria-hidden="true"></a><span class="co"># Step 2: Transfer files from source</span></span>
<span id="cb3-40"><a href="#cb3-40" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 2/6: Transferring files from source..."</span></span>
<span id="cb3-41"><a href="#cb3-41" aria-hidden="true"></a><span class="fu">rsync</span> -avz --progress <span class="kw">\</span></span>
<span id="cb3-42"><a href="#cb3-42" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-content/cache/*'</span> <span class="kw">\</span></span>
<span id="cb3-43"><a href="#cb3-43" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-content/backup*'</span> <span class="kw">\</span></span>
<span id="cb3-44"><a href="#cb3-44" aria-hidden="true"></a>    <span class="st">"</span><span class="va">$SOURCE_HOST</span><span class="st">:</span><span class="va">$SOURCE_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/"</span></span>
<span id="cb3-45"><a href="#cb3-45" aria-hidden="true"></a></span>
<span id="cb3-46"><a href="#cb3-46" aria-hidden="true"></a><span class="co"># Step 3: Backup destination (if exists)</span></span>
<span id="cb3-47"><a href="#cb3-47" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-d</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-48"><a href="#cb3-48" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Step 3/6: Backing up destination..."</span></span>
<span id="cb3-49"><a href="#cb3-49" aria-hidden="true"></a>    <span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb3-50"><a href="#cb3-50" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> core is-installed <span class="op">2&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-51"><a href="#cb3-51" aria-hidden="true"></a>        <span class="ex">wp</span> db export <span class="st">"/backups/dest-before-migration-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span> <span class="kw">||</span> <span class="fu">true</span></span>
<span id="cb3-52"><a href="#cb3-52" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb3-53"><a href="#cb3-53" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-54"><a href="#cb3-54" aria-hidden="true"></a></span>
<span id="cb3-55"><a href="#cb3-55" aria-hidden="true"></a><span class="co"># Step 4: Import database</span></span>
<span id="cb3-56"><a href="#cb3-56" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 4/6: Importing database..."</span></span>
<span id="cb3-57"><a href="#cb3-57" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb3-58"><a href="#cb3-58" aria-hidden="true"></a><span class="ex">wp</span> db import <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">/database.sql.gz"</span></span>
<span id="cb3-59"><a href="#cb3-59" aria-hidden="true"></a></span>
<span id="cb3-60"><a href="#cb3-60" aria-hidden="true"></a><span class="co"># Step 5: Update URLs</span></span>
<span id="cb3-61"><a href="#cb3-61" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 5/6: Updating URLs..."</span></span>
<span id="cb3-62"><a href="#cb3-62" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$OLD_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span> --dry-run --report</span>
<span id="cb3-63"><a href="#cb3-63" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$OLD_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-64"><a href="#cb3-64" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"//</span><span class="va">$(</span><span class="bu">echo</span> <span class="va">$OLD_URL</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s~http[s]*://~~'</span><span class="va">)</span><span class="st">"</span> <span class="st">"//</span><span class="va">$(</span><span class="bu">echo</span> <span class="va">$NEW_URL</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s~http[s]*://~~'</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb3-65"><a href="#cb3-65" aria-hidden="true"></a></span>
<span id="cb3-66"><a href="#cb3-66" aria-hidden="true"></a><span class="co"># Update WordPress options</span></span>
<span id="cb3-67"><a href="#cb3-67" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-68"><a href="#cb3-68" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-69"><a href="#cb3-69" aria-hidden="true"></a></span>
<span id="cb3-70"><a href="#cb3-70" aria-hidden="true"></a><span class="co"># Step 6: Verify and cleanup</span></span>
<span id="cb3-71"><a href="#cb3-71" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 6/6: Verifying migration..."</span></span>
<span id="cb3-72"><a href="#cb3-72" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> core is-installed<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-73"><a href="#cb3-73" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ WordPress installation verified"</span></span>
<span id="cb3-74"><a href="#cb3-74" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb3-75"><a href="#cb3-75" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ WordPress verification failed"</span></span>
<span id="cb3-76"><a href="#cb3-76" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-77"><a href="#cb3-77" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-78"><a href="#cb3-78" aria-hidden="true"></a></span>
<span id="cb3-79"><a href="#cb3-79" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> db check<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-80"><a href="#cb3-80" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ Database healthy"</span></span>
<span id="cb3-81"><a href="#cb3-81" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb3-82"><a href="#cb3-82" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Database issues detected"</span></span>
<span id="cb3-83"><a href="#cb3-83" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-84"><a href="#cb3-84" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-85"><a href="#cb3-85" aria-hidden="true"></a></span>
<span id="cb3-86"><a href="#cb3-86" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb3-87"><a href="#cb3-87" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb3-88"><a href="#cb3-88" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb3-89"><a href="#cb3-89" aria-hidden="true"></a></span>
<span id="cb3-90"><a href="#cb3-90" aria-hidden="true"></a><span class="co"># Cleanup</span></span>
<span id="cb3-91"><a href="#cb3-91" aria-hidden="true"></a><span class="fu">rm</span> -rf <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">"</span></span>
<span id="cb3-92"><a href="#cb3-92" aria-hidden="true"></a></span>
<span id="cb3-93"><a href="#cb3-93" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=== Migration Complete ==="</span></span>
<span id="cb3-94"><a href="#cb3-94" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Site URL: </span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-95"><a href="#cb3-95" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backup: /backups/dest-before-migration-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="push-to-production">Push to Production</h4>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="co"># push-to-production.sh - Push staging to production</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a><span class="va">STAGING_PATH=</span><span class="st">"/var/www/staging"</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a><span class="va">PROD_PATH=</span><span class="st">"/var/www/production"</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a><span class="va">STAGING_URL=</span><span class="st">"https://staging.example.com"</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a><span class="va">PROD_URL=</span><span class="st">"https://example.com"</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a><span class="bu">read</span> -p <span class="st">"This will overwrite production. Continue? (y/n) "</span> -n 1 -r</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a><span class="bu">echo</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a><span class="kw">if [[</span> <span class="ot">!</span> <span class="va">$REPLY</span> =~ ^[Yy]$<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a>    <span class="bu">exit</span> 0</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a><span class="co"># Backup production first</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$PROD_PATH</span><span class="st">"</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backing up production..."</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"/backups/prod-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span><span class="st">.sql.gz"</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true"></a></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a><span class="co"># Export from staging</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$STAGING_PATH</span><span class="st">"</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Exporting staging..."</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true"></a><span class="ex">wp</span> db export /tmp/staging-push.sql.gz</span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true"></a></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true"></a><span class="co"># Copy files</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Copying files..."</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true"></a><span class="fu">rsync</span> -av --delete <span class="kw">\</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-config.php'</span> <span class="kw">\</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true"></a>    <span class="st">"</span><span class="va">$STAGING_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$PROD_PATH</span><span class="st">/"</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true"></a></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true"></a><span class="co"># Import to production</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$PROD_PATH</span><span class="st">"</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Importing database..."</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true"></a><span class="ex">wp</span> db import /tmp/staging-push.sql.gz</span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true"></a></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true"></a><span class="co"># Update URLs</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Updating URLs for production..."</span></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$STAGING_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$PROD_URL</span><span class="st">"</span></span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$PROD_URL</span><span class="st">"</span></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$PROD_URL</span><span class="st">"</span></span>
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true"></a></span>
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb4-43"><a href="#cb4-43" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb4-44"><a href="#cb4-44" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb4-45"><a href="#cb4-45" aria-hidden="true"></a></span>
<span id="cb4-46"><a href="#cb4-46" aria-hidden="true"></a><span class="co"># Cleanup</span></span>
<span id="cb4-47"><a href="#cb4-47" aria-hidden="true"></a><span class="fu">rm</span> /tmp/staging-push.sql.gz</span>
<span id="cb4-48"><a href="#cb4-48" aria-hidden="true"></a></span>
<span id="cb4-49"><a href="#cb4-49" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Staging pushed to production"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="advanced-cloning">Advanced Cloning Features</h3>



<p>Add professional features to cloning automation.</p>



<h4 class="wp-block-heading" id="selective-cloning">Selective Cloning</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="co"># selective-clone.sh - Clone only specific components</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a><span class="va">CLONE_TYPE=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span>  # <span class="ex">database</span>, files, plugins, themes, uploads</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a><span class="kw">case</span> <span class="st">"</span><span class="va">$CLONE_TYPE</span><span class="st">"</span><span class="kw"> in</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a>    database<span class="kw">)</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning database only..."</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a>        <span class="bu">cd</span> <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a>        <span class="ex">wp</span> db export /tmp/db-clone.sql.gz</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a>        <span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a>        <span class="ex">wp</span> db import /tmp/db-clone.sql.gz</span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a>        <span class="fu">rm</span> /tmp/db-clone.sql.gz</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a>    files<span class="kw">)</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning files only..."</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true"></a>        <span class="fu">rsync</span> -av <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/"</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true"></a></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true"></a>    plugins<span class="kw">)</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning plugins..."</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true"></a>        <span class="fu">rsync</span> -av <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/wp-content/plugins/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/wp-content/plugins/"</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true"></a></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true"></a>    themes<span class="kw">)</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning themes..."</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true"></a>        <span class="fu">rsync</span> -av <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/wp-content/themes/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/wp-content/themes/"</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true"></a></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true"></a>    uploads<span class="kw">)</span></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning uploads..."</span></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true"></a>        <span class="fu">rsync</span> -av <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/wp-content/uploads/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/wp-content/uploads/"</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true"></a></span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true"></a>    *<span class="kw">)</span></span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;source&gt; &lt;dest&gt; &lt;database|files|plugins|themes|uploads&gt;"</span></span>
<span id="cb5-40"><a href="#cb5-40" aria-hidden="true"></a>        <span class="bu">exit</span> 1</span>
<span id="cb5-41"><a href="#cb5-41" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-42"><a href="#cb5-42" aria-hidden="true"></a><span class="kw">esac</span></span>
<span id="cb5-43"><a href="#cb5-43" aria-hidden="true"></a></span>
<span id="cb5-44"><a href="#cb5-44" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Selective clone complete"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="clone-with-sanitization">Clone with Sanitization</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="co"># clone-sanitized.sh - Clone for development, remove sensitive data</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="co"># Clone site</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a><span class="fu">bash</span> /usr/local/bin/clone-wordpress-site.sh <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Sanitizing clone for development..."</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a><span class="co"># Deactivate security plugins</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a><span class="ex">wp</span> plugin deactivate wordfence sucuri-scanner --quiet</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true"></a><span class="co"># Remove sensitive data</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Removing sensitive user data..."</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true"></a></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true"></a><span class="co"># Anonymize user emails</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">user_id</span> in <span class="va">$(</span><span class="ex">wp</span> user list --field=ID<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true"></a>    <span class="va">USERNAME=$(</span><span class="ex">wp</span> user get <span class="va">$user_id</span> --field=user_login<span class="va">)</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true"></a>    <span class="ex">wp</span> user update <span class="va">$user_id</span> --user_email=<span class="st">"</span><span class="va">${USERNAME}</span><span class="st">@example.test"</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true"></a></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true"></a><span class="co"># Remove real passwords (force password reset)</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">user_id</span> in <span class="va">$(</span><span class="ex">wp</span> user list --field=ID<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true"></a>    <span class="ex">wp</span> user update <span class="va">$user_id</span> --user_pass=<span class="st">"development"</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true"></a></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true"></a><span class="co"># Remove payment gateway credentials</span></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true"></a><span class="ex">wp</span> option update woocommerce_stripe_settings <span class="st">'{"enabled":"no"}'</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true"></a><span class="ex">wp</span> option update woocommerce_paypal_settings <span class="st">'{"enabled":"no"}'</span></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true"></a></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true"></a><span class="co"># Disable external services</span></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true"></a><span class="ex">wp</span> plugin deactivate google-analytics mailchimp --quiet</span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true"></a></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true"></a><span class="co"># Enable debug mode</span></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true"></a><span class="ex">wp</span> config set WP_DEBUG true --raw</span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true"></a><span class="ex">wp</span> config set WP_DEBUG_LOG true --raw</span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true"></a></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Clone sanitized for development"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="multi-environment">Multi-Environment Sync</h3>



<p>Synchronize WordPress across development, staging, and production.</p>



<h4 class="wp-block-heading" id="environment-sync-system">Environment Sync System</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="co"># sync-environments.sh - Sync between dev/staging/prod</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a><span class="va">OPERATION=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span>  # <span class="ex">pull</span> or push</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="va">ENV_FROM=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span>   # <span class="ex">dev</span>, staging, prod</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a><span class="va">ENV_TO=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span>     # <span class="ex">dev</span>, staging, prod</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a><span class="co"># Environment paths</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a><span class="bu">declare</span> -A <span class="va">PATHS=(</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a>    [<span class="st">"dev"</span>]=<span class="st">"/var/www/dev"</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a>    [<span class="st">"staging"</span>]=<span class="st">"/var/www/staging"</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a>    [<span class="st">"prod"</span>]=<span class="st">"/var/www/production"</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a>)</span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a><span class="co"># Environment URLs</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a><span class="bu">declare</span> -A <span class="va">URLS=(</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a>    [<span class="st">"dev"</span>]=<span class="st">"http://dev.local"</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a>    [<span class="st">"staging"</span>]=<span class="st">"https://staging.example.com"</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a>    [<span class="st">"prod"</span>]=<span class="st">"https://example.com"</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a>)</span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$ENV_TO</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;pull|push&gt; &lt;from_env&gt; &lt;to_env&gt;"</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Environments: dev, staging, prod"</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true"></a></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">${PATHS[$ENV_FROM]}</span><span class="st">"</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">${PATHS[$ENV_TO]}</span><span class="st">"</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true"></a><span class="va">SOURCE_URL=</span><span class="st">"</span><span class="va">${URLS[$ENV_FROM]}</span><span class="st">"</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true"></a><span class="va">DEST_URL=</span><span class="st">"</span><span class="va">${URLS[$ENV_TO]}</span><span class="st">"</span></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true"></a></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Syncing </span><span class="va">$ENV_FROM</span><span class="st"> → </span><span class="va">$ENV_TO</span><span class="st">"</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true"></a></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true"></a><span class="co"># Confirmation for production</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$ENV_TO</span><span class="st">"</span> <span class="ot">==</span> <span class="st">"prod"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true"></a>    <span class="bu">read</span> -p <span class="st">"WARNING: Syncing to production. Continue? (y/n) "</span> -n 1 -r</span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true"></a>    <span class="bu">echo</span></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true"></a>    <span class="kw">if [[</span> <span class="ot">!</span> <span class="va">$REPLY</span> =~ ^[Yy]$<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true"></a>        <span class="bu">exit</span> 0</span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true"></a></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true"></a><span class="co"># Backup destination</span></span>
<span id="cb7-45"><a href="#cb7-45" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb7-46"><a href="#cb7-46" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backing up </span><span class="va">$ENV_TO</span><span class="st">..."</span></span>
<span id="cb7-47"><a href="#cb7-47" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"/backups/</span><span class="va">${ENV_TO}</span><span class="st">-before-sync-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d<span class="va">)</span><span class="st">.sql.gz"</span></span>
<span id="cb7-48"><a href="#cb7-48" aria-hidden="true"></a></span>
<span id="cb7-49"><a href="#cb7-49" aria-hidden="true"></a><span class="co"># Clone</span></span>
<span id="cb7-50"><a href="#cb7-50" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb7-51"><a href="#cb7-51" aria-hidden="true"></a><span class="ex">wp</span> db export /tmp/env-sync.sql.gz</span>
<span id="cb7-52"><a href="#cb7-52" aria-hidden="true"></a></span>
<span id="cb7-53"><a href="#cb7-53" aria-hidden="true"></a><span class="fu">rsync</span> -av <span class="kw">\</span></span>
<span id="cb7-54"><a href="#cb7-54" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-config.php'</span> <span class="kw">\</span></span>
<span id="cb7-55"><a href="#cb7-55" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-content/cache'</span> <span class="kw">\</span></span>
<span id="cb7-56"><a href="#cb7-56" aria-hidden="true"></a>    <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/"</span></span>
<span id="cb7-57"><a href="#cb7-57" aria-hidden="true"></a></span>
<span id="cb7-58"><a href="#cb7-58" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb7-59"><a href="#cb7-59" aria-hidden="true"></a><span class="ex">wp</span> db import /tmp/env-sync.sql.gz</span>
<span id="cb7-60"><a href="#cb7-60" aria-hidden="true"></a></span>
<span id="cb7-61"><a href="#cb7-61" aria-hidden="true"></a><span class="co"># Update URLs</span></span>
<span id="cb7-62"><a href="#cb7-62" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$DEST_URL</span><span class="st">"</span></span>
<span id="cb7-63"><a href="#cb7-63" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$DEST_URL</span><span class="st">"</span></span>
<span id="cb7-64"><a href="#cb7-64" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$DEST_URL</span><span class="st">"</span></span>
<span id="cb7-65"><a href="#cb7-65" aria-hidden="true"></a></span>
<span id="cb7-66"><a href="#cb7-66" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb7-67"><a href="#cb7-67" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb7-68"><a href="#cb7-68" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb7-69"><a href="#cb7-69" aria-hidden="true"></a></span>
<span id="cb7-70"><a href="#cb7-70" aria-hidden="true"></a><span class="fu">rm</span> /tmp/env-sync.sql.gz</span>
<span id="cb7-71"><a href="#cb7-71" aria-hidden="true"></a></span>
<span id="cb7-72"><a href="#cb7-72" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Environment sync complete: </span><span class="va">$ENV_FROM</span><span class="st"> → </span><span class="va">$ENV_TO</span><span class="st">"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="verification">Clone Verification</h3>



<p>Validate clones are complete and functional.</p>



<h4 class="wp-block-heading" id="complete-verification-script">Complete Verification Script</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="co"># verify-clone.sh - Verify WordPress clone</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a><span class="va">CLONE_PATH=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$CLONE_PATH</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;clone_path&gt;"</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$CLONE_PATH</span><span class="st">"</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true"></a></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Verifying WordPress clone..."</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a><span class="co"># Check WordPress is installed</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> core is-installed <span class="op">2&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ WordPress not properly installed"</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ WordPress installed"</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a><span class="co"># Check database connection</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> db check <span class="op">2&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Database connection failed"</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Database connected"</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true"></a></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true"></a><span class="co"># Verify post count matches</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true"></a><span class="co"># (Would need original count passed in for real comparison)</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true"></a><span class="va">POST_COUNT=$(</span><span class="ex">wp</span> post list --format=count<span class="va">)</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Posts: </span><span class="va">$POST_COUNT</span><span class="st">"</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true"></a></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true"></a><span class="co"># Verify user count</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true"></a><span class="va">USER_COUNT=$(</span><span class="ex">wp</span> user list --format=count<span class="va">)</span></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Users: </span><span class="va">$USER_COUNT</span><span class="st">"</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true"></a></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true"></a><span class="co"># Verify plugins</span></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true"></a><span class="va">PLUGIN_COUNT=$(</span><span class="ex">wp</span> plugin list --format=count<span class="va">)</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Plugins: </span><span class="va">$PLUGIN_COUNT</span><span class="st">"</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true"></a></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true"></a><span class="co"># Check for broken URLs</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true"></a><span class="va">SITE_URL=$(</span><span class="ex">wp</span> option get siteurl<span class="va">)</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Site URL: </span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true"></a></span>
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true"></a><span class="co"># Test site accessibility</span></span>
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">curl</span> -f -s <span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span> <span class="op">&gt;</span> /dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-48"><a href="#cb8-48" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ Site accessible"</span></span>
<span id="cb8-49"><a href="#cb8-49" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb8-50"><a href="#cb8-50" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Site not accessible"</span></span>
<span id="cb8-51"><a href="#cb8-51" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-52"><a href="#cb8-52" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-53"><a href="#cb8-53" aria-hidden="true"></a></span>
<span id="cb8-54"><a href="#cb8-54" aria-hidden="true"></a><span class="co"># Verify file permissions</span></span>
<span id="cb8-55"><a href="#cb8-55" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-w</span> wp-content<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-56"><a href="#cb8-56" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ wp-content writable"</span></span>
<span id="cb8-57"><a href="#cb8-57" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb8-58"><a href="#cb8-58" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ wp-content not writable"</span></span>
<span id="cb8-59"><a href="#cb8-59" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-60"><a href="#cb8-60" aria-hidden="true"></a></span>
<span id="cb8-61"><a href="#cb8-61" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Clone verification complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have complete WordPress site cloning and migration automation capabilities.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: Basic cloning</p>



<ul class="wp-block-list">
<li>Practice local clones</li>



<li>Test database operations</li>



<li>Master URL replacement</li>
</ul>



<p><strong>Week 2</strong>: Remote migrations</p>



<ul class="wp-block-list">
<li>Set up SSH access</li>



<li>Transfer between servers</li>



<li>Handle production pushes</li>
</ul>



<p><strong>Week 3</strong>: Advanced features</p>



<ul class="wp-block-list">
<li>Selective cloning</li>



<li>Data sanitization</li>



<li>Multi-environment sync</li>
</ul>



<p><strong>Week 4</strong>: Production deployment</p>



<ul class="wp-block-list">
<li>Build verification systems</li>



<li>Automate complete workflows</li>



<li>Document procedures</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Blue-Green Deployments</a></strong> &#8211; Zero-downtime migrations</li>



<li><strong><a href="#">Database Sync Strategies</a></strong> &#8211; Incremental updates</li>



<li><strong><a href="#">Large Site Optimization</a></strong> &#8211; Handle massive WordPress sites</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download cloning scripts</a></strong> including:</p>



<ul class="wp-block-list">
<li>Complete automation system</li>



<li>Verification tools</li>



<li>Multi-environment management</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>Migration best practices</li>



<li>DevOps workflows</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>WordPress site cloning and migration automation with WP-CLI transforms hours of manual work into fast, reliable, one-command operations you can trust.</p>



<p>What we covered:</p>



<p>✅ Complete local site cloning automation <br>✅ Remote migration between servers <br>✅ Advanced selective and sanitized cloning <br>✅ Multi-environment synchronization <br>✅ Clone verification and validation <br>✅ Production-ready workflows</p>



<p>Master these techniques, and you’ll clone WordPress sites effortlessly—whether creating staging environments, migrating to new hosts, or replicating sites for development.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">WordPress backup automation</a> or <a href="#">deployment pipelines</a>.</p>



<p><strong>Questions about WordPress cloning and migration?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other WordPress developers and agencies.</p>
<p>The post <a href="https://wpclimastery.com/blog/wordpress-site-cloning-and-migration-automation-with-wp-cli/">WordPress Site Cloning and Migration Automation with WP-CLI</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
