<?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>Bash Scripting for WordPress Archives - WP-CLI Mastery</title>
	<atom:link href="https://wpclimastery.com/blog/category/bash-scripting-for-wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>https://wpclimastery.com/blog/category/bash-scripting-for-wordpress/</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>Bash Scripting for WordPress Archives - WP-CLI Mastery</title>
	<link>https://wpclimastery.com/blog/category/bash-scripting-for-wordpress/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Professional Logging and Debugging for WP-CLI Automation Scripts</title>
		<link>https://wpclimastery.com/blog/professional-logging-and-debugging-for-wp-cli-automation-scripts/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Sat, 10 Jan 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Bash Scripting for WordPress]]></category>
		<category><![CDATA[bash debug mode]]></category>
		<category><![CDATA[bash logging]]></category>
		<category><![CDATA[script logging]]></category>
		<category><![CDATA[wordpress automation logging]]></category>
		<category><![CDATA[wp-cli debugging]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=165</guid>

					<description><![CDATA[<p>Your WordPress automation script fails at 3 AM, but you have no idea what went wrong—no logs, no error messages, no trace of what happened. Debugging production scripts without proper...</p>
<p>The post <a href="https://wpclimastery.com/blog/professional-logging-and-debugging-for-wp-cli-automation-scripts/">Professional Logging and Debugging for WP-CLI Automation Scripts</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Your WordPress automation script fails at 3 AM, but you have no idea what went wrong—no logs, no error messages, no trace of what happened. Debugging production scripts without proper logging means guessing, recreating issues, and wasting hours troubleshooting.</p>



<p>Professional logging transforms opaque scripts into transparent, debuggable systems. Track every operation, capture errors with context, monitor script health, and diagnose failures instantly with comprehensive logs that tell the complete story.</p>



<p>In this guide, you’ll learn professional logging and debugging techniques for WP-CLI automation scripts, from basic logging to advanced monitoring systems used by DevOps teams managing critical WordPress infrastructure.</p>



<h3 class="wp-block-heading" id="why-logging">Why Logging Matters for Automation Scripts</h3>



<p><a href="https://www.gnu.org/software/bash/manual/bash.html#Redirections">Bash scripting without logging</a> is like driving blindfolded—you don’t know what’s happening until something crashes.</p>



<h4 class="wp-block-heading" id="problems-without-proper-logging">Problems Without Proper Logging</h4>



<p><strong>Silent failures</strong>: Scripts fail without leaving any trace of what went wrong.</p>



<p><strong>No audit trail</strong>: Can’t verify what scripts did or when they ran.</p>



<p><strong>Difficult debugging</strong>: Recreating issues requires guessing and trial-and-error.</p>



<p><strong>No monitoring</strong>: Can’t track script health or detect degrading performance.</p>



<p><strong>Compliance issues</strong>: Can’t prove what operations were performed when.</p>



<h4 class="wp-block-heading" id="professional-logging-benefits">Professional Logging Benefits</h4>



<p><strong>Instant diagnosis</strong>: Know exactly what failed and why from log messages.</p>



<p><strong>Complete audit trail</strong>: Track every operation for compliance and debugging.</p>



<p><strong>Proactive monitoring</strong>: Detect issues before they become critical failures.</p>



<p><strong>Performance tracking</strong>: Identify bottlenecks and optimization opportunities.</p>



<p><strong>Team collaboration</strong>: Share logs for troubleshooting across teams.</p>



<p>According to <a href="https://cloud.google.com/architecture/devops">DevOps best practices</a>, comprehensive logging reduces mean time to recovery (MTTR) by 80%.</p>



<h3 class="wp-block-heading" id="basic-logging">Basic Logging Implementation</h3>



<p>Start with fundamental logging patterns for WP-CLI scripts.</p>



<h4 class="wp-block-heading" id="simple-log-function">Simple Log Function</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"># basic-logging.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="va">LOG_FILE=</span><span class="st">"/var/log/wp-automation.log"</span></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="fu">log()</span> <span class="kw">{</span></span>
<span id="cb1-7"><a href="#cb1-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="cb1-8"><a href="#cb1-8" aria-hidden="true"></a><span class="kw">}</span></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"># Usage</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Script started"</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Updating WordPress plugins..."</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="ex">wp</span> plugin update --all</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="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="cb1-17"><a href="#cb1-17" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ Plugins updated successfully"</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✗ Plugin update failed"</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true"></a><span class="kw">fi</span></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">log</span> <span class="st">"Script completed"</span></span></code></pre>
</div>



<p><strong>Key Elements</strong>:</p>



<ul class="wp-block-list">
<li>Timestamp for every log entry</li>



<li><code>tee</code> outputs to both terminal and file</li>



<li>Exit codes checked and logged</li>
</ul>



<h4 class="wp-block-heading" id="logging-command-output">Logging Command Output</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>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"/var/log/wp-updates.log"</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb2-6"><a href="#cb2-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="cb2-7"><a href="#cb2-7" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Starting WordPress update"</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a><span class="co"># Capture command output and log it</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a><span class="va">OUTPUT=$(</span><span class="ex">wp</span> core update <span class="op">2&gt;&amp;1</span><span class="va">)</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a><span class="va">EXIT_CODE=$?</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="bu">echo</span> <span class="st">"</span><span class="va">$OUTPUT</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="cb2-16"><a href="#cb2-16" aria-hidden="true"></a></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="va">$EXIT_CODE</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ WordPress updated successfully"</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✗ WordPress update failed with exit code </span><span class="va">$EXIT_CODE</span><span class="st">"</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"Output: </span><span class="va">$OUTPUT</span><span class="st">"</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>



<p>Learn about <a href="https://www.gnu.org/software/bash/manual/bash.html#Redirections">Bash redirection</a> for capturing output.</p>



<h3 class="wp-block-heading" id="log-levels">Log Levels and Structured Logging</h3>



<p>Implement professional log levels for better organization.</p>



<h4 class="wp-block-heading" id="multi-level-logging-system">Multi-Level Logging System</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"># logging-levels.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="va">LOG_FILE=</span><span class="st">"/var/log/wp-automation.log"</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a><span class="va">LOG_LEVEL=</span><span class="st">"</span><span class="va">${LOG_LEVEL:-</span>INFO<span class="va">}</span><span class="st">"</span>  # <span class="ex">Default</span> to INFO</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"># Log level hierarchy: DEBUG &lt; INFO &lt; WARN &lt; ERROR</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a><span class="bu">declare</span> -A <span class="va">LOG_LEVELS=([DEBUG]=</span>0 <span class="va">[INFO]=</span>1 <span class="va">[WARN]=</span>2 <span class="va">[ERROR]=</span>3<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="fu">log()</span> <span class="kw">{</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">level=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a>    <span class="bu">shift</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">message=</span><span class="st">"</span><span class="va">$@</span><span class="st">"</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">timestamp=$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</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="co"># Check if we should log this level</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">${LOG_LEVELS[$level]}</span><span class="st">"</span> <span class="ot">-ge</span> <span class="st">"</span><span class="va">${LOG_LEVELS[$LOG_LEVEL]}</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"[</span><span class="va">$timestamp</span><span class="st">] [</span><span class="va">$level</span><span class="st">] </span><span class="va">$message</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="cb3-19"><a href="#cb3-19" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a><span class="kw">}</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="fu">log_debug()</span> <span class="kw">{</span> <span class="ex">log</span> DEBUG <span class="st">"</span><span class="va">$@</span><span class="st">"</span><span class="kw">;</span> <span class="kw">}</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a><span class="fu">log_info()</span> <span class="kw">{</span> <span class="ex">log</span> INFO <span class="st">"</span><span class="va">$@</span><span class="st">"</span><span class="kw">;</span> <span class="kw">}</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a><span class="fu">log_warn()</span> <span class="kw">{</span> <span class="ex">log</span> WARN <span class="st">"</span><span class="va">$@</span><span class="st">"</span><span class="kw">;</span> <span class="kw">}</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a><span class="fu">log_error()</span> <span class="kw">{</span> <span class="ex">log</span> ERROR <span class="st">"</span><span class="va">$@</span><span class="st">"</span><span class="kw">;</span> <span class="kw">}</span></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 class="co"># Usage examples</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a><span class="ex">log_debug</span> <span class="st">"Starting database backup process"</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a><span class="ex">log_info</span> <span class="st">"Backing up WordPress database"</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a><span class="ex">log_warn</span> <span class="st">"Database size exceeds 1GB, this may take a while"</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a><span class="ex">log_error</span> <span class="st">"Database backup failed: disk full"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="structured-log-format">Structured Log Format</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"># structured-logging.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="fu">log_structured()</span> <span class="kw">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">level=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">component=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">action=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a>    <span class="bu">shift</span> 3</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">message=</span><span class="st">"</span><span class="va">$@</span><span class="st">"</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">local</span> <span class="va">timestamp=$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">hostname=$(</span><span class="fu">hostname</span><span class="va">)</span></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"># JSON-like format for easy parsing</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"{</span><span class="dt">\"</span><span class="st">timestamp</span><span class="dt">\"</span><span class="st">:</span><span class="dt">\"</span><span class="va">$timestamp</span><span class="dt">\"</span><span class="st">,</span><span class="dt">\"</span><span class="st">level</span><span class="dt">\"</span><span class="st">:</span><span class="dt">\"</span><span class="va">$level</span><span class="dt">\"</span><span class="st">,</span><span class="dt">\"</span><span class="st">host</span><span class="dt">\"</span><span class="st">:</span><span class="dt">\"</span><span class="va">$hostname</span><span class="dt">\"</span><span class="st">,</span><span class="dt">\"</span><span class="st">component</span><span class="dt">\"</span><span class="st">:</span><span class="dt">\"</span><span class="va">$component</span><span class="dt">\"</span><span class="st">,</span><span class="dt">\"</span><span class="st">action</span><span class="dt">\"</span><span class="st">:</span><span class="dt">\"</span><span class="va">$action</span><span class="dt">\"</span><span class="st">,</span><span class="dt">\"</span><span class="st">message</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 class="op">&gt;&gt;</span> <span class="st">"</span><span class="va">$LOG_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="co"># Human-readable format for terminal</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[</span><span class="va">$timestamp</span><span class="st">] [</span><span class="va">$level</span><span class="st">] [</span><span class="va">$component</span><span class="st">] </span><span class="va">$action</span><span class="st">: </span><span class="va">$message</span><span class="st">"</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true"></a><span class="co"># Usage</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true"></a><span class="ex">log_structured</span> INFO <span class="st">"wordpress"</span> <span class="st">"plugin-update"</span> <span class="st">"Updating all plugins"</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true"></a><span class="ex">log_structured</span> ERROR <span class="st">"database"</span> <span class="st">"backup"</span> <span class="st">"Failed to create backup: Permission denied"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="debugging-techniques">Debugging Techniques</h3>



<p>Advanced debugging patterns for troubleshooting scripts.</p>



<h4 class="wp-block-heading" id="bash-debug-mode">Bash Debug Mode</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>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a><span class="co"># Enable debug mode with -x flag</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-x</span>  # Print each command before executing</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"># Or use for specific sections</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a><span class="kw">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a>    <span class="kw">set</span> <span class="ex">-x</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a>    <span class="ex">wp</span> plugin update --all</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a>    <span class="ex">wp</span> theme update --all</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a>    <span class="kw">set</span> <span class="ex">+x</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a><span class="kw">}</span> <span class="op">2&gt;&amp;1</span> <span class="kw">|</span> <span class="fu">tee</span> -a debug.log</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"># Verbose WP-CLI output</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a><span class="ex">wp</span> --debug plugin list</span></code></pre>
</div>



<h4 class="wp-block-heading" id="function-tracing">Function Tracing</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>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a><span class="co"># Enable function call tracing</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-o</span> functrace</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="co"># Trace function for debugging</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="fu">trace()</span> <span class="kw">{</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[TRACE] Function: </span><span class="va">${FUNCNAME[1]}</span><span class="st">, Line: </span><span class="va">${BASH_LINENO[0]}</span><span class="st">"</span> <span class="op">&gt;&gt;</span> trace.log</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a><span class="kw">}</span></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="fu">backup_database()</span> <span class="kw">{</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a>    <span class="ex">trace</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a>    <span class="ex">log_info</span> <span class="st">"Starting database backup"</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a>    <span class="ex">wp</span> db export backup.sql.gz</span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a><span class="kw">}</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="fu">update_plugins()</span> <span class="kw">{</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a>    <span class="ex">trace</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true"></a>    <span class="ex">log_info</span> <span class="st">"Updating plugins"</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true"></a>    <span class="ex">wp</span> plugin update --all</span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true"></a></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true"></a><span class="co"># Call functions</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true"></a><span class="ex">backup_database</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true"></a><span class="ex">update_plugins</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="variable-state-logging">Variable State Logging</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>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a><span class="fu">log_var()</span> <span class="kw">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">var_name=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">var_value=</span><span class="st">"</span><span class="va">${!var_name}</span><span class="st">"</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a>    <span class="ex">log_debug</span> <span class="st">"Variable </span><span class="va">$var_name</span><span class="st"> = '</span><span class="va">$var_value</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="co"># Usage</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a><span class="va">BACKUP_DIR=</span><span class="st">"/backups"</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a><span class="va">SITE_URL=</span><span class="st">"https://example.com"</span></span>
<span id="cb7-12"><a href="#cb7-12" 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="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="ex">log_var</span> BACKUP_DIR</span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a><span class="ex">log_var</span> SITE_URL</span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a><span class="ex">log_var</span> PLUGIN_COUNT</span></code></pre>
</div>



<p>Learn about <a href="https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html">Bash debugging</a> techniques.</p>



<h3 class="wp-block-heading" id="error-context">Error Context and Stack Traces</h3>



<p>Capture comprehensive error information for debugging.</p>



<h4 class="wp-block-heading" id="error-handler-with-context">Error Handler with Context</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="kw">set</span> <span class="ex">-euo</span> pipefail</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">LOG_FILE=</span><span class="st">"/var/log/wp-errors.log"</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="fu">error_handler()</span> <span class="kw">{</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">exit_code=$?</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">line_number=$1</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">bash_lineno=${BASH_LINENO[0]}</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">function_name=${FUNCNAME[1]:-</span>main<span class="va">}</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">command=</span><span class="st">"</span><span class="va">${BASH_COMMAND}</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="kw">{</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"=========================================="</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"ERROR OCCURRED"</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"=========================================="</span></span>
<span id="cb8-17"><a href="#cb8-17" 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="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Exit Code: </span><span class="va">$exit_code</span><span class="st">"</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Line Number: </span><span class="va">$line_number</span><span class="st">"</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Function: </span><span class="va">$function_name</span><span class="st">"</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Command: </span><span class="va">$command</span><span class="st">"</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Script: </span><span class="va">$0</span><span class="st">"</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Working Directory: </span><span class="va">$(</span><span class="bu">pwd</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"User: </span><span class="va">$(</span><span class="fu">whoami</span><span class="va">)</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">"Hostname: </span><span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"=========================================="</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true"></a>    <span class="kw">}</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="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"># Capture environment state</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Environment Variables:"</span> <span class="op">&gt;&gt;</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true"></a>    <span class="fu">env</span> <span class="op">&gt;&gt;</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true"></a></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true"></a>    <span class="bu">exit</span> <span class="va">$exit_code</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true"></a><span class="kw">}</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">trap</span> <span class="st">'error_handler ${LINENO}'</span> ERR</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"># Script operations that might fail</span></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true"></a><span class="ex">wp</span> db export backup.sql.gz</span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true"></a><span class="ex">wp</span> plugin update --all</span></code></pre>
</div>



<h4 class="wp-block-heading" id="stack-trace-function">Stack Trace Function</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>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a><span class="fu">print_stack_trace()</span> <span class="kw">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">frame=</span>0</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Stack Trace:"</span> <span class="op">&gt;&amp;2</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="kw">while</span> <span class="bu">caller</span> <span class="va">$frame</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a>        <span class="kw">((</span>frame++<span class="kw">))</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a>    <span class="kw">done</span> <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">line</span> <span class="va">func</span> <span class="va">file</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">"  at </span><span class="va">$func</span><span class="st"> (</span><span class="va">$file</span><span class="st">:</span><span class="va">$line</span><span class="st">)"</span> <span class="op">&gt;&amp;2</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a><span class="fu">error_with_trace()</span> <span class="kw">{</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"ERROR: </span><span class="va">$@</span><span class="st">"</span> <span class="op">&gt;&amp;2</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true"></a>    <span class="ex">print_stack_trace</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true"></a></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true"></a><span class="co"># Usage</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true"></a><span class="fu">backup_db()</span> <span class="kw">{</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true"></a>    <span class="kw">if</span> ! <span class="ex">wp</span> db export backup.sql.gz<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true"></a>        <span class="ex">error_with_trace</span> <span class="st">"Database backup failed"</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true"></a>        <span class="bu">return</span> 1</span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true"></a><span class="kw">}</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="log-rotation">Log Rotation and Management</h3>



<p>Prevent logs from consuming all disk space.</p>



<h4 class="wp-block-heading" id="manual-log-rotation">Manual Log Rotation</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"># rotate-logs.sh - Rotate log files</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">LOG_FILE=</span><span class="st">"/var/log/wp-automation.log"</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a><span class="va">MAX_SIZE_MB=</span>10</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a><span class="va">KEEP_DAYS=</span>30</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="co"># Check log file size</span></span>
<span id="cb10-9"><a href="#cb10-9" 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">$LOG_FILE</span><span class="st">"</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">FILE_SIZE=$(</span><span class="fu">du</span> -m <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">cut</span> -f1<span class="va">)</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$FILE_SIZE</span><span class="st">"</span> <span class="ot">-gt</span> <span class="st">"</span><span class="va">$MAX_SIZE_MB</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Rotating log file (</span><span class="va">${FILE_SIZE}</span><span class="st">MB)"</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"># Archive with timestamp</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true"></a>        <span class="va">ARCHIVE=</span><span class="st">"</span><span class="va">${LOG_FILE}</span><span class="st">.</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d-%H%M%S<span class="va">)</span><span class="st">.gz"</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true"></a>        <span class="fu">gzip</span> -c <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$ARCHIVE</span><span class="st">"</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="co"># Clear current log</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true"></a>        <span class="op">&gt;</span> <span class="st">"</span><span class="va">$LOG_FILE</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="bu">echo</span> <span class="st">"Log rotated to: </span><span class="va">$ARCHIVE</span><span class="st">"</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true"></a></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true"></a><span class="co"># Delete old archives</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true"></a><span class="fu">find</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="va">$LOG_FILE)</span><span class="st">"</span> -name <span class="st">"</span><span class="va">$(</span><span class="fu">basename</span> <span class="va">$LOG_FILE)</span><span class="st">.*.gz"</span> -mtime +<span class="va">$KEEP_DAYS</span> -delete</span></code></pre>
</div>



<h4 class="wp-block-heading" id="using-logrotate">Using logrotate</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"># /etc/logrotate.d/wp-automation</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a><span class="ex">/var/log/wp-automation.log</span> {</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a>    <span class="ex">daily</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a>    <span class="ex">rotate</span> 7</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a>    <span class="ex">compress</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a>    <span class="ex">delaycompress</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a>    <span class="ex">missingok</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a>    <span class="ex">notifempty</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true"></a>    <span class="ex">create</span> 0640 www-data www-data</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true"></a>    <span class="ex">sharedscripts</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true"></a>    <span class="ex">postrotate</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true"></a>        <span class="co"># Optional: restart service if needed</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true"></a>    <span class="ex">endscript</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true"></a>}</span></code></pre>
</div>



<p>Learn about <a href="https://linux.die.net/man/8/logrotate">logrotate configuration</a>.</p>



<h3 class="wp-block-heading" id="performance-logging">Performance and Timing Logs</h3>



<p>Track script performance and identify bottlenecks.</p>



<h4 class="wp-block-heading" id="execution-time-logging">Execution Time Logging</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>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a><span class="fu">log_timed()</span> <span class="kw">{</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">description=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a>    <span class="bu">shift</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">command=</span><span class="st">"</span><span class="va">$@</span><span class="st">"</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true"></a>    <span class="ex">log_info</span> <span class="st">"Starting: </span><span class="va">$description</span><span class="st">"</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">start_time=$(</span><span class="fu">date</span> +%s<span class="va">)</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="co"># Execute command</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true"></a>    <span class="bu">eval</span> <span class="st">"</span><span class="va">$command</span><span class="st">"</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">exit_code=$?</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="bu">local</span> <span class="va">end_time=$(</span><span class="fu">date</span> +%s<span class="va">)</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">duration=$((</span>end_time - start_time<span class="va">))</span></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="kw">if</span><span class="bu"> [</span> <span class="va">$exit_code</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true"></a>        <span class="ex">log_info</span> <span class="st">"✓ Completed: </span><span class="va">$description</span><span class="st"> (</span><span class="va">${duration}</span><span class="st">s)"</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true"></a>        <span class="ex">log_error</span> <span class="st">"✗ Failed: </span><span class="va">$description</span><span class="st"> (</span><span class="va">${duration}</span><span class="st">s, exit code: </span><span class="va">$exit_code</span><span class="st">)"</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true"></a></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true"></a>    <span class="bu">return</span> <span class="va">$exit_code</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true"></a><span class="kw">}</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"># Usage</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true"></a><span class="ex">log_timed</span> <span class="st">"Database export"</span> <span class="st">"wp db export backup.sql.gz"</span></span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true"></a><span class="ex">log_timed</span> <span class="st">"Plugin updates"</span> <span class="st">"wp plugin update --all"</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true"></a><span class="ex">log_timed</span> <span class="st">"Cache flush"</span> <span class="st">"wp cache flush"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="performance-benchmarking">Performance Benchmarking</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>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a><span class="fu">benchmark()</span> <span class="kw">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">operation=</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="bu">local</span> <span class="va">iterations=</span><span class="st">"</span><span class="va">${2:-</span>10<span class="va">}</span><span class="st">"</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="ex">log_info</span> <span class="st">"Benchmarking: </span><span class="va">$operation</span><span class="st"> (</span><span class="va">$iterations</span><span class="st"> iterations)"</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true"></a></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">total_time=</span>0</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">for</span> <span class="ex">i</span> in <span class="va">$(</span><span class="fu">seq</span> 1 <span class="va">$iterations)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true"></a>        <span class="bu">local</span> <span class="va">start=$(</span><span class="fu">date</span> +%s%N<span class="va">)</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true"></a>        <span class="bu">eval</span> <span class="st">"</span><span class="va">$operation</span><span class="st">"</span> <span class="op">&gt;</span>/dev/null <span class="op">2&gt;&amp;1</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true"></a>        <span class="bu">local</span> <span class="va">end=$(</span><span class="fu">date</span> +%s%N<span class="va">)</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">local</span> <span class="va">duration=$((</span> (end - start) / 1000000 <span class="va">))</span>  # <span class="va">Convert</span> <span class="va">to</span> <span class="va">milliseconds</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true"></a>        <span class="va">total_time=$((</span>total_time + duration<span class="va">))</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true"></a>    <span class="kw">done</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="bu">local</span> <span class="va">avg_time=$((</span>total_time / iterations<span class="va">))</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="ex">log_info</span> <span class="st">"Benchmark results: </span><span class="va">${avg_time}</span><span class="st">ms average (</span><span class="va">${iterations}</span><span class="st"> runs)"</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true"></a><span class="kw">}</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"># Usage</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true"></a><span class="ex">benchmark</span> <span class="st">"wp option get siteurl"</span> 5</span></code></pre>
</div>



<h3 class="wp-block-heading" id="log-analysis">Log Aggregation and Analysis</h3>



<p>Analyze logs for insights and troubleshooting.</p>



<h4 class="wp-block-heading" id="log-analysis-scripts">Log Analysis Scripts</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"># analyze-logs.sh - Extract insights from logs</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">LOG_FILE=</span><span class="st">"/var/log/wp-automation.log"</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"WordPress Automation Log Analysis"</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=================================="</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</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"># Count log levels</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Log Levels:"</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"  ERROR:   </span><span class="va">$(</span><span class="fu">grep</span> -c <span class="st">'\[ERROR\]'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"  WARN:    </span><span class="va">$(</span><span class="fu">grep</span> -c <span class="st">'\[WARN\]'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"  INFO:    </span><span class="va">$(</span><span class="fu">grep</span> -c <span class="st">'\[INFO\]'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true"></a><span class="bu">echo</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"># Recent errors</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Recent Errors (last 10):"</span></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true"></a><span class="fu">grep</span> <span class="st">'\[ERROR\]'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tail</span> -10</span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true"></a></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true"></a><span class="co"># Most common operations</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Most Frequent Operations:"</span></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true"></a><span class="fu">grep</span> -oP <span class="st">'(?&lt;=\] ).*?(?=:)'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">sort</span> <span class="kw">|</span> <span class="fu">uniq</span> -c <span class="kw">|</span> <span class="fu">sort</span> -rn <span class="kw">|</span> <span class="fu">head</span> -10</span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true"></a></span>
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true"></a><span class="co"># Script execution times</span></span>
<span id="cb14-28"><a href="#cb14-28" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Average Execution Times:"</span></span>
<span id="cb14-29"><a href="#cb14-29" aria-hidden="true"></a><span class="fu">grep</span> -oP <span class="st">'Completed.*?\(\K[0-9]+(?=s\))'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">awk</span> <span class="st">'{sum+=$1; count++} END {print "Average: " sum/count "s"}'</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="error-report-generation">Error Report Generation</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"># generate-error-report.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/wp-automation.log"</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true"></a><span class="va">REPORT_FILE=</span><span class="st">"/tmp/error-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="cb15-6"><a href="#cb15-6" aria-hidden="true"></a><span class="va">EMAIL=</span><span class="st">"admin@example.com"</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="kw">{</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"WordPress Automation Error Report"</span></span>
<span id="cb15-10"><a href="#cb15-10" 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="cb15-11"><a href="#cb15-11" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"=================================="</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true"></a></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true"></a>    <span class="co"># Errors in last 24 hours</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Errors in Last 24 Hours:"</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true"></a>    <span class="fu">grep</span> <span class="st">'\[ERROR\]'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">grep</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="kw">|</span> <span class="fu">nl</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</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="co"># Failed operations</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Failed Operations:"</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true"></a>    <span class="fu">grep</span> <span class="st">'✗ Failed'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tail</span> -20</span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">""</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true"></a></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true"></a>    <span class="co"># Critical errors</span></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Critical Issues:"</span></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true"></a>    <span class="fu">grep</span> -i <span class="st">'critical\|fatal\|emergency'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tail</span> -10</span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true"></a></span>
<span id="cb15-28"><a href="#cb15-28" 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="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"># Email report if errors found</span></span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true"></a><span class="va">ERROR_COUNT=$(</span><span class="fu">grep</span> -c <span class="st">'\[ERROR\]'</span> <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="kw">||</span> <span class="fu">true</span><span class="va">)</span></span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$ERROR_COUNT</span><span class="st">"</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true"></a>    <span class="ex">mail</span> -s <span class="st">"WordPress Automation Errors: </span><span class="va">$ERROR_COUNT</span><span class="st"> found"</span> <span class="st">"</span><span class="va">$EMAIL</span><span class="st">"</span> <span class="op">&lt;</span> <span class="st">"</span><span class="va">$REPORT_FILE</span><span class="st">"</span></span>
<span id="cb15-34"><a href="#cb15-34" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="centralized-logging">Centralized Logging Systems</h3>



<p>Send logs to centralized logging platforms.</p>



<h4 class="wp-block-heading" id="syslog-integration">Syslog Integration</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>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true"></a><span class="co"># Log to both file and syslog</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true"></a><span class="fu">log_to_syslog()</span> <span class="kw">{</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">level=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true"></a>    <span class="bu">shift</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">message=</span><span class="st">"</span><span class="va">$@</span><span class="st">"</span></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"># Map to syslog levels</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true"></a>    <span class="kw">case</span> <span class="st">"</span><span class="va">$level</span><span class="st">"</span><span class="kw"> in</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true"></a>        ERROR<span class="kw">)</span> <span class="va">priority=</span><span class="st">"err"</span> <span class="kw">;;</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true"></a>        WARN<span class="kw">)</span>  <span class="va">priority=</span><span class="st">"warning"</span> <span class="kw">;;</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true"></a>        INFO<span class="kw">)</span>  <span class="va">priority=</span><span class="st">"info"</span> <span class="kw">;;</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true"></a>        DEBUG<span class="kw">)</span> <span class="va">priority=</span><span class="st">"debug"</span> <span class="kw">;;</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true"></a>        *<span class="kw">)</span> <span class="va">priority=</span><span class="st">"notice"</span> <span class="kw">;;</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true"></a>    <span class="kw">esac</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true"></a></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true"></a>    <span class="co"># Log to file</span></span>
<span id="cb16-19"><a href="#cb16-19" 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">$level</span><span class="st">] </span><span class="va">$message</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-20"><a href="#cb16-20" aria-hidden="true"></a></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true"></a>    <span class="co"># Log to syslog</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true"></a>    <span class="ex">logger</span> -t <span class="st">"wp-automation"</span> -p <span class="st">"user.</span><span class="va">${priority}</span><span class="st">"</span> <span class="st">"</span><span class="va">$message</span><span class="st">"</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true"></a></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true"></a><span class="co"># Usage</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true"></a><span class="ex">log_to_syslog</span> INFO <span class="st">"Starting WordPress backup"</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true"></a><span class="ex">log_to_syslog</span> ERROR <span class="st">"Backup failed: disk full"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="json-logging-for-parsing">JSON Logging for Parsing</h4>



<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">#!/bin/bash</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true"></a></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true"></a><span class="fu">log_json()</span> <span class="kw">{</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">level=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true"></a>    <span class="bu">shift</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">message=</span><span class="st">"</span><span class="va">$@</span><span class="st">"</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true"></a></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">json=$(</span><span class="fu">cat</span> <span class="op">&lt;&lt;EOF</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true"></a>{</span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true"></a>  "timestamp": "<span class="va">$(</span><span class="fu">date</span> -u +%Y-%m-%dT%H:%M:%SZ<span class="va">)</span>",</span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true"></a>  "level": "<span class="va">$level</span>",</span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true"></a>  "service": "wp-automation",</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true"></a>  "hostname": "<span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span>",</span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true"></a>  "message": "<span class="va">$message</span>",</span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true"></a>  "script": "<span class="va">$0</span>",</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true"></a>  "pid": <span class="va">$</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true"></a>}</span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true"></a><span class="op">EOF</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true"></a><span class="va">)</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true"></a></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"</span><span class="va">$json</span><span class="st">"</span> <span class="op">&gt;&gt;</span> /var/log/wp-automation.json</span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true"></a></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true"></a><span class="co"># Usage</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true"></a><span class="ex">log_json</span> <span class="st">"info"</span> <span class="st">"WordPress backup started"</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true"></a><span class="ex">log_json</span> <span class="st">"error"</span> <span class="st">"Plugin update failed"</span></span></code></pre>
</div>



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



<p>You now have professional logging and debugging skills for production-ready WP-CLI automation.</p>



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



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



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



<li>Add timestamps and levels</li>



<li>Practice log file rotation</li>
</ul>



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



<ul class="wp-block-list">
<li>Use debug modes</li>



<li>Add error handlers</li>



<li>Capture stack traces</li>
</ul>



<p><strong>Week 3</strong>: Performance tracking</p>



<ul class="wp-block-list">
<li>Log execution times</li>



<li>Benchmark operations</li>



<li>Identify bottlenecks</li>
</ul>



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



<ul class="wp-block-list">
<li>Set up log analysis</li>



<li>Configure alerting</li>



<li>Implement centralized logging</li>
</ul>



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



<ol class="wp-block-list">
<li><strong><a href="#">Distributed Tracing</a></strong> &#8211; Track operations across systems</li>



<li><strong><a href="#">Log Analytics</a></strong> &#8211; Advanced log parsing and insights</li>



<li><strong><a href="#">Monitoring Dashboards</a></strong> &#8211; Visualize log data</li>
</ol>



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



<p><strong><a href="#">Download logging templates</a></strong> including:</p>



<ul class="wp-block-list">
<li>Complete logging systems</li>



<li>Analysis scripts</li>



<li>Monitoring tools</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>Debugging best practices</li>



<li>DevOps logging strategies</li>
</ul>



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



<p>Professional logging and debugging transform fragile WordPress automation scripts into transparent, maintainable systems that provide complete visibility into operations.</p>



<p>What we covered:</p>



<p>✅ Basic logging implementation with timestamps ✅ Multi-level logging systems (DEBUG, INFO, WARN, ERROR) ✅ Advanced debugging techniques and tracing ✅ Error context and stack trace capture ✅ Log rotation and management ✅ Performance tracking and analysis</p>



<p>Master these techniques, and you’ll never struggle to debug production scripts again—comprehensive logs tell you exactly what happened, when, and why.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">monitoring and alerting</a> or <a href="#">production debugging workflows</a>.</p>



<p><strong>Questions about logging WP-CLI automation scripts?</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/professional-logging-and-debugging-for-wp-cli-automation-scripts/">Professional Logging and Debugging for WP-CLI Automation Scripts</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Bulletproof Error Handling in Bash Scripts for WP-CLI (Complete Guide)</title>
		<link>https://wpclimastery.com/blog/bulletproof-error-handling-in-bash-scripts-for-wp-cli-complete-guide/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Fri, 05 Dec 2025 09:00:00 +0000</pubDate>
				<category><![CDATA[Bash Scripting for WordPress]]></category>
		<category><![CDATA[plugin-test]]></category>
		<category><![CDATA[rest-api]]></category>
		<category><![CDATA[yoast-seo]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=136</guid>

					<description><![CDATA[<p>Your WordPress automation script runs perfectly 99% of the time. Then one day it silently fails during a database import, deletes files you meant to keep, or corrupts data because...</p>
<p>The post <a href="https://wpclimastery.com/blog/bulletproof-error-handling-in-bash-scripts-for-wp-cli-complete-guide/">Bulletproof Error Handling in Bash Scripts for WP-CLI (Complete Guide)</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Your WordPress automation script runs perfectly 99% of the time. Then one day it silently fails during a database import, deletes files you meant to keep, or corrupts data because a command returned an error you never checked. Production is down.</p>
<p>Bash scripts without proper error handling are disasters waiting to happen. One unchecked exit code, one missing validation, and your automation becomes your biggest liability instead of your greatest asset.</p>
<p>In this guide, you’ll learn professional error handling techniques that prevent script failures, protect your data, and make WP-CLI automation scripts production-ready and bulletproof.</p>
<h3 id="why-error-handling">Why Error Handling Matters for WP-CLI Scripts</h3>
<p><a href="https://www.gnu.org/software/bash/manual/">Bash scripting</a> by default continues executing after errors occur, which is dangerous for WordPress operations.</p>
<h4 id="problems-with-poor-error-handling">Problems with Poor Error Handling</h4>
<p><strong>Silent failures</strong>: Scripts continue after failed database exports, creating incomplete backups.</p>
<p><strong>Data corruption</strong>: Import scripts run on wrong databases because connection checks were skipped.</p>
<p><strong>Partial operations</strong>: Plugin updates fail halfway through, leaving sites in broken states.</p>
<p><strong>No recovery</strong>: Scripts can’t rollback or cleanup after failures.</p>
<p><strong>Debugging nightmares</strong>: No logs or error messages make troubleshooting impossible.</p>
<h4 id="professional-error-handling-benefits">Professional Error Handling Benefits</h4>
<p><strong>Early failure detection</strong>: Scripts stop immediately when errors occur.</p>
<p><strong>Safe operations</strong>: Validate inputs and check preconditions before making changes.</p>
<p><strong>Automatic cleanup</strong>: Trap errors and perform cleanup even during failures.</p>
<p><strong>Detailed logging</strong>: Track exactly what failed and why for quick debugging.</p>
<p><strong>Production-ready</strong>: Confidence to run scripts on live sites without supervision.</p>
<p>According to <a href="https://puppet.com/resources/report/state-of-devops-report/">DevOps research</a>, organizations with robust error handling in automation scripts experience 60% fewer outages.</p>
<h3 id="fundamentals">Bash Error Handling Fundamentals</h3>
<p>Master the core error handling mechanisms in Bash.</p>
<h4 id="exit-codes-and-variable">Exit Codes and $? Variable</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"># Every command returns exit code</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="co"># 0 = success, non-zero = failure</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="ex">wp</span> core version</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a><span class="bu">echo</span> <span class="va">$?</span>  # Prints 0 if successful</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="ex">wp</span> plugin install nonexistent-plugin</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a><span class="bu">echo</span> <span class="va">$?</span>  # Prints non-zero (1) <span class="kw">if</span> <span class="ex">failed</span></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"># Check exit code immediately</span></span>
<span id="cb1-11"><a href="#cb1-11" 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="cb1-12"><a href="#cb1-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Success&quot;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Failed&quot;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>
<h4 id="better-check-exit-codes-inline">Better: Check Exit Codes Inline</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"># Check command directly in if statement</span></span>
<span id="cb2-2"><a href="#cb2-2" 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="cb2-3"><a href="#cb2-3" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;WordPress is installed&quot;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;WordPress not found&quot;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a><span class="co"># Using &amp;&amp; for success chaining</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a><span class="ex">wp</span> db export backup.sql <span class="kw">&amp;&amp;</span> <span class="bu">echo</span> <span class="st">&quot;Backup successful&quot;</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"># Using || for failure handling</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a><span class="ex">wp</span> db export backup.sql <span class="kw">||</span> <span class="kw">{</span> <span class="bu">echo</span> <span class="st">&quot;Backup failed!&quot;</span><span class="kw">;</span> <span class="bu">exit</span> 1<span class="kw">;</span> <span class="kw">}</span></span></code></pre>
</div>
<p><strong>Pro Tip</strong>: Always check exit codes for destructive operations like database imports, file deletions, or updates.</p>
<h4 id="set-error-handling-mode">Set Error Handling Mode</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>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a><span class="co"># Exit on any error</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-e</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="co"># Exit on undefined variables</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-u</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"># Pipe failures cause script failure</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-o</span> pipefail</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"># Combined (recommended)</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a><span class="co"># Now script exits automatically on errors</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a><span class="ex">wp</span> db export backup.sql  # Script exits if this fails</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a><span class="ex">wp</span> plugin update --all    # Never runs if above failed</span></code></pre>
</div>
<p>Learn more about <a href="https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html">Bash set options</a>.</p>
<h3 id="validation">Validation and Precondition Checking</h3>
<p>Verify assumptions before executing dangerous operations.</p>
<h4 id="check-file-existence">Check File Existence</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="kw">set</span> <span class="ex">-euo</span> pipefail</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">BACKUP_FILE=</span><span class="st">&quot;/backups/database.sql.gz&quot;</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"># Check file exists before import</span></span>
<span id="cb4-7"><a href="#cb4-7" 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">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Error: Backup file not found: </span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a><span class="co"># Verify file size (not empty)</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a><span class="va">FILE_SIZE=$(</span><span class="fu">stat</span> -c%s <span class="st">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span><span class="va">)</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">&quot;</span><span class="va">$FILE_SIZE</span><span class="st">&quot;</span> <span class="ot">-lt</span> 1000<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Error: Backup file too small (</span><span class="va">${FILE_SIZE}</span><span class="st"> bytes), may be corrupted&quot;</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true"></a><span class="kw">fi</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"># Safe to import</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a><span class="ex">wp</span> db import <span class="st">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span></span></code></pre>
</div>
<h4 id="validate-wordpress-installation">Validate WordPress Installation</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="kw">set</span> <span class="ex">-euo</span> pipefail</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"># Check WordPress is installed</span></span>
<span id="cb5-5"><a href="#cb5-5" 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="cb5-6"><a href="#cb5-6" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Error: WordPress not installed in current directory&quot;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a><span class="co"># Check database connection</span></span>
<span id="cb5-11"><a href="#cb5-11" 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="cb5-12"><a href="#cb5-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Error: Database connection failed&quot;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a><span class="kw">fi</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">&quot;✓ WordPress installation validated&quot;</span></span></code></pre>
</div>
<h4 id="check-required-commands-exist">Check Required Commands Exist</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="kw">set</span> <span class="ex">-euo</span> pipefail</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"># Function to check command availability</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="fu">check_command()</span> <span class="kw">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a>    <span class="kw">if</span> ! <span class="bu">command</span> -v <span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span> <span class="op">&amp;&gt;</span> /dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">&quot;Error: Required command &#39;</span><span class="va">$1</span><span class="st">&#39; not found&quot;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">&quot;Install it with: apt-get install </span><span class="va">$1</span><span class="st">&quot;</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a>        <span class="bu">exit</span> 1</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a><span class="kw">}</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="co"># Verify dependencies</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a><span class="ex">check_command</span> wp</span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a><span class="ex">check_command</span> mysql</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true"></a><span class="ex">check_command</span> gzip</span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true"></a></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;✓ All required commands available&quot;</span></span></code></pre>
</div>
<h3 id="error-trapping">Error Trapping and Cleanup</h3>
<p>Handle errors gracefully and cleanup resources even during failures.</p>
<h4 id="basic-trap-command">Basic Trap Command</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="kw">set</span> <span class="ex">-euo</span> pipefail</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"># Cleanup function</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="fu">cleanup()</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">&quot;Cleaning up temporary files...&quot;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a>    <span class="fu">rm</span> -f /tmp/temp-backup-*.sql</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Cleanup complete&quot;</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a><span class="kw">}</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><span class="co"># Register cleanup to run on exit</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a><span class="bu">trap</span> cleanup EXIT</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="co"># Script continues normally</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;Starting backup...&quot;</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a><span class="ex">wp</span> db export /tmp/temp-backup-<span class="va">$(</span><span class="fu">date</span> +%s<span class="va">)</span>.sql.gz</span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a><span class="co"># cleanup() runs automatically when script exits</span></span></code></pre>
</div>
<h4 id="error-specific-trap">Error-Specific Trap</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="kw">set</span> <span class="ex">-euo</span> pipefail</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"># Error handler</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a><span class="fu">error_handler()</span> <span class="kw">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">exit_code=$?</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">line_number=$1</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">&quot;ERROR: Script failed at line </span><span class="va">$line_number</span><span class="st"> with exit code </span><span class="va">$exit_code</span><span class="st">&quot;</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Rolling back changes...&quot;</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"># Perform rollback operations</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a>    <span class="ex">wp</span> db import /backups/before-update.sql.gz <span class="op">2&gt;</span>/dev/null <span class="kw">||</span> <span class="fu">true</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="bu">exit</span> <span class="va">$exit_code</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a><span class="kw">}</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"># Trap errors and call error_handler with line number</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a><span class="bu">trap</span> <span class="st">&#39;error_handler ${LINENO}&#39;</span> ERR</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="co"># Backup before changes</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a><span class="ex">wp</span> db export /backups/before-update.sql.gz</span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a><span class="co"># Risky operation</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a><span class="ex">wp</span> plugin update --all</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"># If above fails, error_handler restores database</span></span></code></pre>
</div>
<p><strong>Use Case</strong>: Automatically restore database backups if update operations fail mid-process.</p>
<h4 id="advanced-trap-with-multiple-signals">Advanced Trap with Multiple Signals</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="kw">set</span> <span class="ex">-euo</span> pipefail</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="va">TEMP_DIR=</span><span class="st">&quot;/tmp/wp-deploy-</span><span class="va">$$</span><span class="st">&quot;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a><span class="va">BACKUP_FILE=</span><span class="st">&quot;&quot;</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"># Comprehensive cleanup</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a><span class="fu">cleanup()</span> <span class="kw">{</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">exit_code=$?</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="kw">if</span><span class="bu"> [</span> <span class="va">$exit_code</span> <span class="ot">-ne</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">&quot;Script failed (exit code: </span><span class="va">$exit_code</span><span class="st">)&quot;</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">&quot;Performing emergency cleanup...&quot;</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="co"># Remove temporary directory</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true"></a>    [ <span class="ex">-d</span> <span class="st">&quot;</span><span class="va">$TEMP_DIR</span><span class="st">&quot;</span> ] <span class="kw">&amp;&amp;</span> <span class="fu">rm</span> -rf <span class="st">&quot;</span><span class="va">$TEMP_DIR</span><span class="st">&quot;</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true"></a></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true"></a>    <span class="co"># Remove temporary backup</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true"></a>    [ <span class="ex">-n</span> <span class="st">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span> ] <span class="kw">&amp;&amp;</span> <span class="fu">rm</span> -f <span class="st">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</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="bu">echo</span> <span class="st">&quot;Cleanup complete&quot;</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true"></a></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true"></a><span class="co"># Trap multiple signals</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true"></a><span class="bu">trap</span> cleanup EXIT ERR INT TERM</span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true"></a></span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true"></a><span class="co"># Create temp directory</span></span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">&quot;</span><span class="va">$TEMP_DIR</span><span class="st">&quot;</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"># Store backup location</span></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true"></a><span class="va">BACKUP_FILE=</span><span class="st">&quot;/tmp/backup-</span><span class="va">$$</span><span class="st">.sql.gz&quot;</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="co"># Script operations...</span></span></code></pre>
</div>
<h3 id="input-validation">Input Validation and Argument Parsing</h3>
<p>Validate script arguments and user inputs before processing.</p>
<h4 id="validate-required-arguments">Validate Required Arguments</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="kw">set</span> <span class="ex">-euo</span> pipefail</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"># Check argument count</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="va">$#</span> <span class="ot">-lt</span> 2<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Usage: </span><span class="va">$0</span><span class="st"> &lt;source_url&gt; &lt;target_url&gt;&quot;</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Example: </span><span class="va">$0</span><span class="st"> https://oldsite.com https://newsite.com&quot;</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a><span class="kw">fi</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="va">SOURCE_URL=</span><span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a><span class="va">TARGET_URL=</span><span class="st">&quot;</span><span class="va">$2</span><span class="st">&quot;</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"># Validate URL format</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true"></a><span class="kw">if [[</span> <span class="ot">!</span> <span class="st">&quot;</span><span class="va">$SOURCE_URL</span><span class="st">&quot;</span> =~ ^https?://<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">&quot;Error: Source URL must start with http:// or https://&quot;</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true"></a></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true"></a><span class="kw">if [[</span> <span class="ot">!</span> <span class="st">&quot;</span><span class="va">$TARGET_URL</span><span class="st">&quot;</span> =~ ^https?://<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Error: Target URL must start with http:// or https://&quot;</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true"></a><span class="kw">fi</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"># Safe to proceed</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">&quot;</span><span class="va">$SOURCE_URL</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$TARGET_URL</span><span class="st">&quot;</span></span></code></pre>
</div>
<h4 id="validate-user-confirmation">Validate User Confirmation</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="kw">set</span> <span class="ex">-euo</span> pipefail</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="bu">echo</span> <span class="st">&quot;WARNING: This will delete all WordPress posts&quot;</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;This action cannot be undone!&quot;</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a><span class="bu">read</span> -p <span class="st">&quot;Type &#39;DELETE&#39; to confirm: &quot;</span> <span class="va">CONFIRMATION</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="kw">if</span><span class="bu"> [</span> <span class="st">&quot;</span><span class="va">$CONFIRMATION</span><span class="st">&quot;</span> <span class="ot">!=</span> <span class="st">&quot;DELETE&quot;</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Operation cancelled&quot;</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true"></a>    <span class="bu">exit</span> 0</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true"></a><span class="kw">fi</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="co"># User confirmed, proceed with deletion</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true"></a><span class="ex">wp</span> post delete <span class="va">$(</span><span class="ex">wp</span> post list --format=ids<span class="va">)</span> --force</span></code></pre>
</div>
<h4 id="validate-numeric-inputs">Validate Numeric Inputs</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="va">DAYS_TO_KEEP=</span><span class="st">&quot;</span><span class="va">${1:-</span>7<span class="va">}</span><span class="st">&quot;</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"># Ensure input is a number</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a><span class="kw">if</span> !<span class="kw"> [[</span> <span class="st">&quot;</span><span class="va">$DAYS_TO_KEEP</span><span class="st">&quot;</span> =~ ^[0-9]+$<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Error: Days must be a positive number&quot;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true"></a><span class="kw">fi</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"># Ensure reasonable range</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">&quot;</span><span class="va">$DAYS_TO_KEEP</span><span class="st">&quot;</span> <span class="ot">-lt</span> 1<span class="bu"> ]</span> <span class="kw">||</span><span class="bu"> [</span> <span class="st">&quot;</span><span class="va">$DAYS_TO_KEEP</span><span class="st">&quot;</span> <span class="ot">-gt</span> 365<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;Error: Days must be between 1 and 365&quot;</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true"></a><span class="kw">fi</span></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="co"># Delete old backups</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true"></a><span class="fu">find</span> /backups -name <span class="st">&quot;*.sql.gz&quot;</span> -mtime +<span class="va">$DAYS_TO_KEEP</span> -delete</span></code></pre>
</div>
<h3 id="logging">Logging and Error Reporting</h3>
<p>Track script execution and failures with comprehensive logging.</p>
<h4 id="basic-logging-function">Basic Logging Function</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="kw">set</span> <span class="ex">-euo</span> pipefail</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">LOG_FILE=</span><span class="st">&quot;/var/log/wp-automation.log&quot;</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"># Logging function</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">level=</span><span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true"></a>    <span class="bu">shift</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">message=</span><span class="st">&quot;</span><span class="va">$@</span><span class="st">&quot;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">timestamp=$(</span><span class="fu">date</span> <span class="st">&#39;+%Y-%m-%d %H:%M:%S&#39;</span><span class="va">)</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;[</span><span class="va">$timestamp</span><span class="st">] [</span><span class="va">$level</span><span class="st">] </span><span class="va">$message</span><span class="st">&quot;</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">&quot;</span><span class="va">$LOG_FILE</span><span class="st">&quot;</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true"></a><span class="kw">}</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="co"># Usage</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true"></a><span class="ex">log</span> INFO <span class="st">&quot;Starting WordPress backup&quot;</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true"></a><span class="ex">log</span> WARNING <span class="st">&quot;Database size is large, this may take a while&quot;</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true"></a><span class="ex">log</span> ERROR <span class="st">&quot;Backup failed: disk full&quot;</span></span></code></pre>
</div>
<h4 id="log-with-script-context">Log with Script Context</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="kw">set</span> <span class="ex">-euo</span> pipefail</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">LOG_FILE=</span><span class="st">&quot;/var/log/wp-scripts.log&quot;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true"></a><span class="va">SCRIPT_NAME=$(</span><span class="fu">basename</span> <span class="st">&quot;</span><span class="va">$0</span><span class="st">&quot;</span><span class="va">)</span></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="fu">log()</span> <span class="kw">{</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">&#39;+%Y-%m-%d %H:%M:%S&#39;</span><span class="va">)</span><span class="st">] [</span><span class="va">$SCRIPT_NAME</span><span class="st">] </span><span class="va">$@</span><span class="st">&quot;</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">&quot;</span><span class="va">$LOG_FILE</span><span class="st">&quot;</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true"></a></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Script started&quot;</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Backing up database...&quot;</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true"></a></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> db export backup.sql.gz<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">&quot;✓ Database backup successful&quot;</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">&quot;✗ Database backup failed&quot;</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true"></a><span class="kw">fi</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="ex">log</span> <span class="st">&quot;Script completed&quot;</span></span></code></pre>
</div>
<h4 id="email-notifications-on-failure">Email Notifications on Failure</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="kw">set</span> <span class="ex">-euo</span> pipefail</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">ADMIN_EMAIL=</span><span class="st">&quot;admin@example.com&quot;</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="co"># Error handler with email notification</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true"></a><span class="fu">error_notify()</span> <span class="kw">{</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">exit_code=$?</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">line_number=$1</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true"></a></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true"></a>    <span class="co"># Prepare error message</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true"></a>    <span class="va">ERROR_MSG=</span><span class="st">&quot;WordPress automation script failed</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true"></a></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true"></a><span class="st">Script: </span><span class="va">$0</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true"></a><span class="st">Line: </span><span class="va">$line_number</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true"></a><span class="st">Exit Code: </span><span class="va">$exit_code</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true"></a><span class="st">Time: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true"></a><span class="st">Server: </span><span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true"></a></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true"></a><span class="st">Please investigate immediately.&quot;</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true"></a></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true"></a>    <span class="co"># Log error</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$ERROR_MSG</span><span class="st">&quot;</span> <span class="op">&gt;&gt;</span> /var/log/wp-errors.log</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 class="co"># Send email</span></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$ERROR_MSG</span><span class="st">&quot;</span> <span class="kw">|</span> <span class="ex">mail</span> -s <span class="st">&quot;ALERT: WordPress Script Failure&quot;</span> <span class="st">&quot;</span><span class="va">$ADMIN_EMAIL</span><span class="st">&quot;</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true"></a></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true"></a>    <span class="bu">exit</span> <span class="va">$exit_code</span></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true"></a></span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true"></a><span class="bu">trap</span> <span class="st">&#39;error_notify ${LINENO}&#39;</span> ERR</span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true"></a></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true"></a><span class="co"># Script operations...</span></span></code></pre>
</div>
<h3 id="production-patterns">Production-Ready Error Handling Patterns</h3>
<p>Complete error handling templates for common WP-CLI operations.</p>
<h4 id="safe-database-migration-script">Safe Database Migration 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="kw">set</span> <span class="ex">-euo</span> pipefail</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"># Configuration</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a><span class="va">SOURCE_URL=</span><span class="st">&quot;https://staging.example.com&quot;</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true"></a><span class="va">TARGET_URL=</span><span class="st">&quot;https://production.example.com&quot;</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true"></a><span class="va">BACKUP_DIR=</span><span class="st">&quot;/backups/migrations&quot;</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">&quot;/var/log/wp-migration.log&quot;</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true"></a></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true"></a><span class="co"># Logging</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">&#39;+%Y-%m-%d %H:%M:%S&#39;</span><span class="va">)</span><span class="st">] </span><span class="va">$@</span><span class="st">&quot;</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">&quot;</span><span class="va">$LOG_FILE</span><span class="st">&quot;</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true"></a><span class="kw">}</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="co"># Error handler</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true"></a><span class="fu">error_handler()</span> <span class="kw">{</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">&quot;ERROR: Migration failed at line </span><span class="va">$1</span><span class="st">&quot;</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">&quot;Rolling back to previous state...&quot;</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">if</span><span class="bu"> [</span> <span class="ot">-f</span> <span class="st">&quot;</span><span class="va">$ROLLBACK_BACKUP</span><span class="st">&quot;</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true"></a>        <span class="ex">wp</span> db import <span class="st">&quot;</span><span class="va">$ROLLBACK_BACKUP</span><span class="st">&quot;</span> <span class="kw">&amp;&amp;</span> <span class="ex">log</span> <span class="st">&quot;✓ Rollback successful&quot;</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true"></a>    <span class="kw">fi</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="bu">exit</span> 1</span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true"></a></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true"></a><span class="bu">trap</span> <span class="st">&#39;error_handler ${LINENO}&#39;</span> ERR</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="co"># Start migration</span></span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;=== WordPress Migration Started ===&quot;</span></span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true"></a></span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true"></a><span class="co"># Validate preconditions</span></span>
<span id="cb16-33"><a href="#cb16-33" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Validating environment...&quot;</span></span>
<span id="cb16-34"><a href="#cb16-34" aria-hidden="true"></a><span class="ex">wp</span> core is-installed <span class="kw">||</span> <span class="kw">{</span> <span class="ex">log</span> <span class="st">&quot;ERROR: WordPress not installed&quot;</span><span class="kw">;</span> <span class="bu">exit</span> 1<span class="kw">;</span> <span class="kw">}</span></span>
<span id="cb16-35"><a href="#cb16-35" aria-hidden="true"></a><span class="ex">wp</span> db check <span class="kw">||</span> <span class="kw">{</span> <span class="ex">log</span> <span class="st">&quot;ERROR: Database connection failed&quot;</span><span class="kw">;</span> <span class="bu">exit</span> 1<span class="kw">;</span> <span class="kw">}</span></span>
<span id="cb16-36"><a href="#cb16-36" aria-hidden="true"></a></span>
<span id="cb16-37"><a href="#cb16-37" aria-hidden="true"></a><span class="co"># Create backup directory</span></span>
<span id="cb16-38"><a href="#cb16-38" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">&quot;</span><span class="va">$BACKUP_DIR</span><span class="st">&quot;</span></span>
<span id="cb16-39"><a href="#cb16-39" aria-hidden="true"></a></span>
<span id="cb16-40"><a href="#cb16-40" aria-hidden="true"></a><span class="co"># Backup current state</span></span>
<span id="cb16-41"><a href="#cb16-41" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Creating rollback backup...&quot;</span></span>
<span id="cb16-42"><a href="#cb16-42" aria-hidden="true"></a><span class="va">ROLLBACK_BACKUP=</span><span class="st">&quot;</span><span class="va">$BACKUP_DIR</span><span class="st">/rollback-</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&quot;</span></span>
<span id="cb16-43"><a href="#cb16-43" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">&quot;</span><span class="va">$ROLLBACK_BACKUP</span><span class="st">&quot;</span> <span class="kw">||</span> <span class="kw">{</span> <span class="ex">log</span> <span class="st">&quot;ERROR: Backup failed&quot;</span><span class="kw">;</span> <span class="bu">exit</span> 1<span class="kw">;</span> <span class="kw">}</span></span>
<span id="cb16-44"><a href="#cb16-44" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;✓ Rollback backup created: </span><span class="va">$ROLLBACK_BACKUP</span><span class="st">&quot;</span></span>
<span id="cb16-45"><a href="#cb16-45" aria-hidden="true"></a></span>
<span id="cb16-46"><a href="#cb16-46" aria-hidden="true"></a><span class="co"># Verify backup</span></span>
<span id="cb16-47"><a href="#cb16-47" aria-hidden="true"></a><span class="va">BACKUP_SIZE=$(</span><span class="fu">stat</span> -c%s <span class="st">&quot;</span><span class="va">$ROLLBACK_BACKUP</span><span class="st">&quot;</span><span class="va">)</span></span>
<span id="cb16-48"><a href="#cb16-48" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">&quot;</span><span class="va">$BACKUP_SIZE</span><span class="st">&quot;</span> <span class="ot">-lt</span> 1000<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb16-49"><a href="#cb16-49" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">&quot;ERROR: Backup file too small, aborting&quot;</span></span>
<span id="cb16-50"><a href="#cb16-50" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb16-51"><a href="#cb16-51" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb16-52"><a href="#cb16-52" aria-hidden="true"></a></span>
<span id="cb16-53"><a href="#cb16-53" aria-hidden="true"></a><span class="co"># Perform search-replace (dry run first)</span></span>
<span id="cb16-54"><a href="#cb16-54" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Testing URL replacement...&quot;</span></span>
<span id="cb16-55"><a href="#cb16-55" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> search-replace <span class="st">&quot;</span><span class="va">$SOURCE_URL</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$TARGET_URL</span><span class="st">&quot;</span> --dry-run --report<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb16-56"><a href="#cb16-56" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">&quot;ERROR: Dry run failed&quot;</span></span>
<span id="cb16-57"><a href="#cb16-57" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb16-58"><a href="#cb16-58" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb16-59"><a href="#cb16-59" aria-hidden="true"></a></span>
<span id="cb16-60"><a href="#cb16-60" aria-hidden="true"></a><span class="co"># Execute actual replacement</span></span>
<span id="cb16-61"><a href="#cb16-61" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Executing URL replacement...&quot;</span></span>
<span id="cb16-62"><a href="#cb16-62" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">&quot;</span><span class="va">$SOURCE_URL</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$TARGET_URL</span><span class="st">&quot;</span> --report</span>
<span id="cb16-63"><a href="#cb16-63" aria-hidden="true"></a></span>
<span id="cb16-64"><a href="#cb16-64" aria-hidden="true"></a><span class="co"># Verify replacement</span></span>
<span id="cb16-65"><a href="#cb16-65" aria-hidden="true"></a><span class="va">REMAINING=$(</span><span class="ex">wp</span> search-replace <span class="st">&quot;</span><span class="va">$SOURCE_URL</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$TARGET_URL</span><span class="st">&quot;</span> --dry-run --report <span class="kw">|</span> <span class="fu">grep</span> -c <span class="st">&quot;</span><span class="va">$SOURCE_URL</span><span class="st">&quot;</span> <span class="kw">||</span> <span class="fu">true</span><span class="va">)</span></span>
<span id="cb16-66"><a href="#cb16-66" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">&quot;</span><span class="va">$REMAINING</span><span class="st">&quot;</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb16-67"><a href="#cb16-67" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">&quot;WARNING: Some URLs may not have been replaced&quot;</span></span>
<span id="cb16-68"><a href="#cb16-68" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb16-69"><a href="#cb16-69" aria-hidden="true"></a></span>
<span id="cb16-70"><a href="#cb16-70" aria-hidden="true"></a><span class="co"># Update WordPress options</span></span>
<span id="cb16-71"><a href="#cb16-71" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Updating WordPress options...&quot;</span></span>
<span id="cb16-72"><a href="#cb16-72" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">&quot;</span><span class="va">$TARGET_URL</span><span class="st">&quot;</span></span>
<span id="cb16-73"><a href="#cb16-73" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">&quot;</span><span class="va">$TARGET_URL</span><span class="st">&quot;</span></span>
<span id="cb16-74"><a href="#cb16-74" aria-hidden="true"></a></span>
<span id="cb16-75"><a href="#cb16-75" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb16-76"><a href="#cb16-76" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Clearing caches...&quot;</span></span>
<span id="cb16-77"><a href="#cb16-77" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb16-78"><a href="#cb16-78" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb16-79"><a href="#cb16-79" aria-hidden="true"></a></span>
<span id="cb16-80"><a href="#cb16-80" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;=== Migration Completed Successfully ===&quot;</span></span>
<span id="cb16-81"><a href="#cb16-81" aria-hidden="true"></a><span class="ex">log</span> <span class="st">&quot;Rollback backup available at: </span><span class="va">$ROLLBACK_BACKUP</span><span class="st">&quot;</span></span></code></pre>
</div>
<h4 id="safe-plugin-update-with-fallback">Safe Plugin Update with Fallback</h4>
<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">#!/bin/bash</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true"></a></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true"></a><span class="va">BACKUP_FILE=</span><span class="st">&quot;/tmp/before-plugin-update-</span><span class="va">$$</span><span class="st">.sql.gz&quot;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true"></a></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true"></a><span class="co"># Cleanup function</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true"></a><span class="fu">cleanup()</span> <span class="kw">{</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true"></a>    <span class="fu">rm</span> -f <span class="st">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true"></a></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true"></a><span class="bu">trap</span> cleanup EXIT</span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true"></a></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true"></a><span class="co"># Error handler</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true"></a><span class="fu">error_handler()</span> <span class="kw">{</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;ERROR: Plugin update failed, restoring backup...&quot;</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true"></a></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> <span class="st">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true"></a>        <span class="ex">wp</span> db import <span class="st">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span> <span class="kw">&amp;&amp;</span> <span class="bu">echo</span> <span class="st">&quot;✓ Database restored&quot;</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true"></a></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true"></a></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true"></a><span class="bu">trap</span> error_handler ERR</span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true"></a></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true"></a><span class="co"># Backup database</span></span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;Creating safety backup...&quot;</span></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">&quot;</span><span class="va">$BACKUP_FILE</span><span class="st">&quot;</span></span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true"></a></span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true"></a><span class="co"># Check for available updates</span></span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true"></a><span class="va">UPDATES=$(</span><span class="ex">wp</span> plugin list --update=available --format=count<span class="va">)</span></span>
<span id="cb17-32"><a href="#cb17-32" aria-hidden="true"></a></span>
<span id="cb17-33"><a href="#cb17-33" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">&quot;</span><span class="va">$UPDATES</span><span class="st">&quot;</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb17-34"><a href="#cb17-34" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">&quot;No plugin updates available&quot;</span></span>
<span id="cb17-35"><a href="#cb17-35" aria-hidden="true"></a>    <span class="bu">exit</span> 0</span>
<span id="cb17-36"><a href="#cb17-36" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb17-37"><a href="#cb17-37" aria-hidden="true"></a></span>
<span id="cb17-38"><a href="#cb17-38" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$UPDATES</span><span class="st"> plugin(s) have updates available&quot;</span></span>
<span id="cb17-39"><a href="#cb17-39" aria-hidden="true"></a></span>
<span id="cb17-40"><a href="#cb17-40" aria-hidden="true"></a><span class="co"># Update plugins</span></span>
<span id="cb17-41"><a href="#cb17-41" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;Updating plugins...&quot;</span></span>
<span id="cb17-42"><a href="#cb17-42" aria-hidden="true"></a><span class="ex">wp</span> plugin update --all</span>
<span id="cb17-43"><a href="#cb17-43" aria-hidden="true"></a></span>
<span id="cb17-44"><a href="#cb17-44" aria-hidden="true"></a><span class="co"># Verify WordPress still works</span></span>
<span id="cb17-45"><a href="#cb17-45" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;Verifying WordPress installation...&quot;</span></span>
<span id="cb17-46"><a href="#cb17-46" aria-hidden="true"></a><span class="ex">wp</span> core is-installed <span class="kw">||</span> <span class="ex">error_handler</span></span>
<span id="cb17-47"><a href="#cb17-47" aria-hidden="true"></a></span>
<span id="cb17-48"><a href="#cb17-48" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;✓ All plugins updated successfully&quot;</span></span>
<span id="cb17-49"><a href="#cb17-49" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">&quot;Backup file will be deleted on exit&quot;</span></span></code></pre>
</div>
<h3 id="next-steps">Next Steps</h3>
<p>You now have professional error handling skills for WP-CLI Bash scripts.</p>
<h4 id="recommended-learning-path">Recommended Learning Path</h4>
<p><strong>Week 1</strong>: Basic error handling</p>
<ul>
<li>Implement exit code checking</li>
<li>Add input validation</li>
<li>Use set -euo pipefail</li>
</ul>
<p><strong>Week 2</strong>: Advanced trapping</p>
<ul>
<li>Create cleanup functions</li>
<li>Implement error handlers</li>
<li>Build rollback mechanisms</li>
</ul>
<p><strong>Week 3</strong>: Logging and monitoring</p>
<ul>
<li>Add comprehensive logging</li>
<li>Set up email notifications</li>
<li>Create error tracking</li>
</ul>
<p><strong>Week 4</strong>: Production hardening</p>
<ul>
<li>Review all scripts for error handling</li>
<li>Create script templates</li>
<li>Document recovery procedures</li>
</ul>
<h4 id="advanced-topics">Advanced Topics</h4>
<ol type="1">
<li><strong><a href="#">Bash Script Testing</a></strong> &#8211; Unit testing for Bash scripts</li>
<li><strong><a href="#">Monitoring and Alerting</a></strong> &#8211; Production script monitoring</li>
<li><strong><a href="#">Incident Response</a></strong> &#8211; Handling script failures in production</li>
</ol>
<h4 id="get-more-resources">Get More Resources</h4>
<p><strong><a href="#">Download error handling templates</a></strong> including:</p>
<ul>
<li>Production-ready script templates</li>
<li>Error handling checklist</li>
<li>Common error patterns</li>
</ul>
<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>
<ul>
<li>Weekly WP-CLI tutorials</li>
<li>Advanced scripting techniques</li>
<li>DevOps best practices</li>
</ul>
<h3 id="conclusion">Conclusion</h3>
<p>Proper error handling transforms fragile scripts into production-ready automation that you can trust with critical WordPress operations.</p>
<p>What we covered:</p>
<p>✅ Exit codes and error detection fundamentals ✅ Validation and precondition checking ✅ Error trapping and automatic cleanup with trap ✅ Input validation and argument parsing ✅ Comprehensive logging and error reporting ✅ Production-ready error handling patterns</p>
<p>Master these techniques, and you’ll write WordPress automation scripts that gracefully handle failures, protect your data, and make debugging trivial.</p>
<p><strong>Ready for more?</strong> Learn <a href="#">advanced Bash scripting patterns</a> or <a href="#">WP-CLI script testing</a>.</p>
<p><strong>Questions about error handling in WP-CLI scripts?</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/bulletproof-error-handling-in-bash-scripts-for-wp-cli-complete-guide/">Bulletproof Error Handling in Bash Scripts for WP-CLI (Complete Guide)</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Parse Command Line Arguments in WP-CLI Bash Scripts</title>
		<link>https://wpclimastery.com/blog/how-to-parse-command-line-arguments-in-wp-cli-bash-scripts/</link>
					<comments>https://wpclimastery.com/blog/how-to-parse-command-line-arguments-in-wp-cli-bash-scripts/#respond</comments>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Mon, 24 Nov 2025 11:16:24 +0000</pubDate>
				<category><![CDATA[Bash Scripting for WordPress]]></category>
		<category><![CDATA[bash argument parsing]]></category>
		<category><![CDATA[bash getopts]]></category>
		<category><![CDATA[bash parameters]]></category>
		<category><![CDATA[command line arguments]]></category>
		<category><![CDATA[wp-cli scripting]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=228</guid>

					<description><![CDATA[<p>When building automation scripts for WordPress using WP-CLI, the ability to parse command line arguments effectively transforms rigid scripts into flexible, reusable tools. Whether you&#8217;re managing multiple sites or creating...</p>
<p>The post <a href="https://wpclimastery.com/blog/how-to-parse-command-line-arguments-in-wp-cli-bash-scripts/">How to Parse Command Line Arguments in WP-CLI Bash Scripts</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When building automation scripts for WordPress using WP-CLI, the ability to parse command line arguments effectively transforms rigid scripts into flexible, reusable tools. Whether you&#8217;re managing multiple sites or creating custom deployment workflows, understanding argument parsing is essential for professional WordPress development.</p>



<h2 class="wp-block-heading" id="why-parse-arguments-in-wp-cli-scripts">Why Parse Arguments in WP-CLI Scripts?</h2>



<p>Command line argument parsing enables your Bash scripts to accept dynamic input, making them adaptable to different scenarios without code modifications. Instead of hardcoding site URLs, environment types, or backup paths, you can pass these values as arguments when executing your scripts.</p>



<p>This approach brings several advantages: increased script reusability, reduced maintenance overhead, better error handling, and improved user experience. A well-designed script with proper argument parsing can serve multiple purposes across different WordPress installations.</p>



<h2 class="wp-block-heading" id="understanding-positional-parameters">Understanding Positional Parameters</h2>



<p>The simplest form of argument parsing uses positional parameters. In Bash, arguments passed to a script are automatically assigned to special variables:&nbsp;<code>$1</code>&nbsp;for the first argument,&nbsp;<code>$2</code>&nbsp;for the second, and so on. The&nbsp;<code>$0</code>&nbsp;variable contains the script name itself.</p>



<pre class="wp-block-code"><code>#!/bin/bash
<em># Simple WP-CLI backup script with positional parameters</em>

SITE_PATH=$1
BACKUP_DIR=$2

wp --path="$SITE_PATH" db export "$BACKUP_DIR/database-$(date +%Y%m%d).sql"
</code></pre>



<p>Execute this script with:&nbsp;<code>./backup.sh /var/www/html /backups</code></p>



<p>While positional parameters work for simple cases, they have limitations. Users must remember the exact order of arguments, and the script offers no built-in way to handle optional parameters or provide helpful usage information.</p>



<h2 class="wp-block-heading" id="using-getopts-for-named-options">Using getopts for Named Options</h2>



<p>The&nbsp;<code>getopts</code>&nbsp;command provides a more sophisticated approach to argument parsing, allowing you to define named options with single-character flags. This method significantly improves script usability and maintainability.</p>



<pre class="wp-block-code"><code>#!/bin/bash
<em># WP-CLI deployment script with getopts</em>

usage() {
    echo "Usage: $0 -p &lt;path&gt; -e &lt;environment&gt; &#91;-b]"
    echo "  -p    WordPress installation path"
    echo "  -e    Environment (dev|staging|prod)"
    echo "  -b    Create backup before deployment"
    exit 1
}

BACKUP=false

while getopts "p:e:bh" opt; do
    case $opt in
        p) WP_PATH="$OPTARG" ;;
        e) ENVIRONMENT="$OPTARG" ;;
        b) BACKUP=true ;;
        h) usage ;;
        \?) echo "Invalid option: -$OPTARG" &gt;&amp;2; usage ;;
        :) echo "Option -$OPTARG requires an argument" &gt;&amp;2; usage ;;
    esac
done

<em># Validate required arguments</em>
if &#91;&#91; -z "$WP_PATH" ]] || &#91;&#91; -z "$ENVIRONMENT" ]]; then
    echo "Error: Missing required arguments"
    usage
fi

<em># Script logic continues here</em>
if &#91;&#91; "$BACKUP" == true ]]; then
    wp --path="$WP_PATH" db export "backup-pre-deploy-$(date +%Y%m%d-%H%M%S).sql"
fi
</code></pre>



<p>In this example, options followed by a colon (like&nbsp;<code>p:</code>&nbsp;and&nbsp;<code>e:</code>) require arguments, while standalone letters (like&nbsp;<code>b</code>) act as flags. The&nbsp;<code>OPTARG</code>&nbsp;variable holds the value passed to options requiring arguments.</p>



<h2 class="wp-block-heading" id="advanced-argument-validation">Advanced Argument Validation</h2>



<p>Robust scripts validate input before processing. Argument validation prevents errors, protects against malicious input, and provides clear feedback when users make mistakes.</p>



<pre class="wp-block-code"><code>#!/bin/bash
<em># WP-CLI site migration script with validation</em>

validate_path() {
    if &#91;&#91; ! -d "$1" ]]; then
        echo "Error: Path '$1' does not exist"
        exit 1
    fi

    if &#91;&#91; ! -f "$1/wp-config.php" ]]; then
        echo "Error: '$1' is not a WordPress installation"
        exit 1
    fi
}

validate_environment() {
    local env=$1
    case $env in
        dev|development|staging|production|prod)
            return 0
            ;;
        *)
            echo "Error: Invalid environment '$env'"
            echo "Allowed values: dev, staging, production"
            exit 1
            ;;
    esac
}

<em># After parsing arguments with getopts</em>
validate_path "$WP_PATH"
validate_environment "$ENVIRONMENT"
</code></pre>



<h2 class="wp-block-heading" id="handling-long-form-options">Handling Long-Form Options</h2>



<p>While getopts handles short options well, it doesn&#8217;t natively support long-form options like&nbsp;<code>--path</code>&nbsp;or&nbsp;<code>--environment</code>. For scripts requiring both short and long options, you can implement manual parsing:</p>



<pre class="wp-block-code"><code>#!/bin/bash

while &#91;&#91; $# -gt 0 ]]; do
    case $1 in
        -p|--path)
            WP_PATH="$2"
            shift 2
            ;;
        -e|--environment)
            ENVIRONMENT="$2"
            shift 2
            ;;
        --dry-run)
            DRY_RUN=true
            shift
            ;;
        -h|--help)
            usage
            ;;
        *)
            echo "Unknown option: $1"
            usage
            ;;
    esac
done
</code></pre>



<p>The&nbsp;<code>shift</code>&nbsp;command removes processed arguments from the parameter list, allowing the loop to progress through all provided options.</p>



<h2 class="wp-block-heading" id="practical-example-multi-site-update-script">Practical Example: Multi-Site Update Script</h2>



<p>Here&#8217;s a complete example demonstrating argument parsing in a real-world WP-CLI script:</p>



<pre class="wp-block-code"><code>#!/bin/bash
<em># Update multiple WordPress sites with flexible options</em>

set -euo pipefail

usage() {
    cat &lt;&lt; EOF
Usage: $0 -s &lt;sites&gt; &#91;OPTIONS]

Required:
    -s, --sites       Comma-separated list of site paths

Options:
    -c, --core        Update WordPress core
    -p, --plugins     Update plugins
    -t, --themes      Update themes
    -a, --all         Update everything
    --exclude-plugin  Plugin to exclude (can be used multiple times)
    --dry-run         Show what would be updated without making changes
    -h, --help        Display this help message

Example:
    $0 -s "/var/www/site1,/var/www/site2" --all --exclude-plugin akismet
EOF
    exit 1
}

<em># Initialize variables</em>
SITES=""
UPDATE_CORE=false
UPDATE_PLUGINS=false
UPDATE_THEMES=false
DRY_RUN=false
EXCLUDED_PLUGINS=()

<em># Parse arguments</em>
while &#91;&#91; $# -gt 0 ]]; do
    case $1 in
        -s|--sites) SITES="$2"; shift 2 ;;
        -c|--core) UPDATE_CORE=true; shift ;;
        -p|--plugins) UPDATE_PLUGINS=true; shift ;;
        -t|--themes) UPDATE_THEMES=true; shift ;;
        -a|--all) UPDATE_CORE=true; UPDATE_PLUGINS=true; UPDATE_THEMES=true; shift ;;
        --exclude-plugin) EXCLUDED_PLUGINS+=("$2"); shift 2 ;;
        --dry-run) DRY_RUN=true; shift ;;
        -h|--help) usage ;;
        *) echo "Unknown option: $1"; usage ;;
    esac
done

<em># Validate required arguments</em>
if &#91;&#91; -z "$SITES" ]]; then
    echo "Error: Sites parameter is required"
    usage
fi

<em># Convert comma-separated sites to array</em>
IFS=',' read -ra SITE_ARRAY &lt;&lt;&lt; "$SITES"

<em># Process each site</em>
for site in "${SITE_ARRAY&#91;@]}"; do
    echo "Processing: $site"

    if &#91;&#91; "$UPDATE_CORE" == true ]]; then
        if &#91;&#91; "$DRY_RUN" == true ]]; then
            wp --path="$site" core check-update
        else
            wp --path="$site" core update
        fi
    fi

    if &#91;&#91; "$UPDATE_PLUGINS" == true ]]; then
        EXCLUDE_ARGS=""
        for plugin in "${EXCLUDED_PLUGINS&#91;@]}"; do
            EXCLUDE_ARGS+=" --exclude=$plugin"
        done

        if &#91;&#91; "$DRY_RUN" == true ]]; then
            wp --path="$site" plugin list --update=available
        else
            wp --path="$site" plugin update --all $EXCLUDE_ARGS
        fi
    fi

    if &#91;&#91; "$UPDATE_THEMES" == true ]]; then
        if &#91;&#91; "$DRY_RUN" == true ]]; then
            wp --path="$site" theme list --update=available
        else
            wp --path="$site" theme update --all
        fi
    fi
done

echo "Update process completed successfully"
</code></pre>



<p>This script demonstrates several best practices: comprehensive usage documentation, boolean flags for optional features, array handling for multiple values, validation of required parameters, and safe execution with&nbsp;<code>set -euo pipefail</code>.</p>



<h2 class="wp-block-heading" id="best-practices-for-argument-parsing">Best Practices for Argument Parsing</h2>



<p>Always provide clear usage documentation that users can access with&nbsp;<code>-h</code>&nbsp;or&nbsp;<code>--help</code>. Validate all input before processing to catch errors early. Use meaningful variable names that clarify the purpose of each argument.</p>



<p>Set default values for optional parameters to ensure predictable behavior. Implement proper error handling with informative messages. Consider the order of operations when multiple flags interact.</p>



<p>For production scripts, add the&nbsp;<code>set -euo pipefail</code>&nbsp;directive at the beginning. This makes your script exit on errors, prevents using undefined variables, and ensures pipeline failures are caught.</p>



<h2 class="wp-block-heading" id="testing-your-argument-parsing">Testing Your Argument Parsing</h2>



<p>Test your scripts with various input combinations: missing required arguments, invalid values, conflicting options, and edge cases. Create a test suite that validates expected behavior:</p>



<pre class="wp-block-code"><code><em># Test missing required argument</em>
./script.sh  <em># Should show usage</em>

<em># Test invalid environment</em>
./script.sh -p /var/www/html -e invalid  <em># Should error</em>

<em># Test dry run mode</em>
./script.sh -s "/var/www/site1" --all --dry-run  <em># Should only show what would change</em>
</code></pre>



<h2 class="wp-block-heading" id="related-links">Related Links</h2>



<ul class="wp-block-list">
<li><a href="https://wp-cli.org/">WP-CLI Official Documentation</a></li>



<li><a href="https://tldp.org/LDP/abs/html/">Bash Scripting Guide &#8211; Advanced Topics</a></li>



<li><a href="https://developer.wordpress.org/cli/commands/">WP-CLI Commands Reference</a></li>



<li><a href="https://developer.wordpress.org/apis/">WordPress Automation Best Practices</a></li>



<li><a href="https://www.shellcheck.net/">Shell Script Security Considerations</a></li>
</ul>
<p>The post <a href="https://wpclimastery.com/blog/how-to-parse-command-line-arguments-in-wp-cli-bash-scripts/">How to Parse Command Line Arguments in WP-CLI Bash Scripts</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpclimastery.com/blog/how-to-parse-command-line-arguments-in-wp-cli-bash-scripts/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Writing Reusable Bash Functions for WordPress Automation</title>
		<link>https://wpclimastery.com/blog/writing-reusable-bash-functions-for-wordpress-automation/</link>
					<comments>https://wpclimastery.com/blog/writing-reusable-bash-functions-for-wordpress-automation/#respond</comments>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Mon, 10 Nov 2025 09:00:00 +0000</pubDate>
				<category><![CDATA[Bash Scripting for WordPress]]></category>
		<category><![CDATA[bash functions]]></category>
		<category><![CDATA[bash wordpress automation]]></category>
		<category><![CDATA[reusable bash code]]></category>
		<category><![CDATA[shell functions wordpress]]></category>
		<category><![CDATA[wordpress bash]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/writing-reusable-bash-functions-for-wordpress-automation/</guid>

					<description><![CDATA[<p>If you&#8217;re writing WordPress automation scripts with WP-CLI, you&#8217;ve probably found yourself copy-pasting the same code blocks over and over. Database exports, plugin updates, backup routines—the same patterns repeat across...</p>
<p>The post <a href="https://wpclimastery.com/blog/writing-reusable-bash-functions-for-wordpress-automation/">Writing Reusable Bash Functions for WordPress Automation</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>If you&#8217;re writing WordPress automation scripts with WP-CLI, you&#8217;ve probably found yourself copy-pasting the same code blocks over and over. Database exports, plugin updates, backup routines—the same patterns repeat across different scripts.</p>



<p>This is where Bash functions become your secret weapon.</p>



<p>In this guide, you&#8217;ll learn how to write reusable, production-ready Bash functions for WordPress automation. We&#8217;ll cover parameter validation, error handling, logging, and real-world examples you can use immediately in your WP-CLI scripts.</p>



<h3 class="wp-block-heading" id="why-use-functions-in-bash-scripts-why-functions">Why Use Functions in Bash Scripts?</h3>



<p>Functions are reusable blocks of code that make your scripts:</p>



<p><strong>More Maintainable</strong>: Fix a bug once in the function, not in 10 different scripts.</p>



<p><strong>Easier to Read</strong>:&nbsp;<code>backup_wordpress_database</code>&nbsp;is clearer than 20 lines of inline code.</p>



<p><strong>More Testable</strong>: Test individual functions independently.</p>



<p><strong>DRY (Don&#8217;t Repeat Yourself)</strong>: Write once, use everywhere.</p>



<p><strong>Professional</strong>: Production-ready scripts use functions extensively.</p>



<h4 class="wp-block-heading" id="before-functions-repetitive-code">Before Functions: Repetitive Code</h4>



<p>Here&#8217;s what many WordPress automation scripts look like without functions:</p>



<pre class="wp-block-code"><code>#!/bin/bash
<em># Script 1: Backup site A</em>
cd /var/www/siteA
wp db export /backups/siteA-$(date +%Y%m%d).sql
tar -czf /backups/siteA-files-$(date +%Y%m%d).tar.gz .
echo "Backup completed for Site A"

<em># Script 2: Backup site B (almost identical!)</em>
cd /var/www/siteB
wp db export /backups/siteB-$(date +%Y%m%d).sql
tar -czf /backups/siteB-files-$(date +%Y%m%d).tar.gz .
echo "Backup completed for Site B"
</code></pre>



<p>This violates DRY principles and becomes a maintenance nightmare.</p>



<h4 class="wp-block-heading" id="after-functions-clean-and-reusable">After Functions: Clean and Reusable</h4>



<p>With functions, the same logic becomes:</p>



<pre class="wp-block-code"><code>#!/bin/bash

<em># Reusable function</em>
backup_wordpress() {
    local wp_path=$1
    local backup_dir=$2
    local site_name=$(basename "$wp_path")
    local timestamp=$(date +%Y%m%d)

    cd "$wp_path" || return 1
    wp db export "${backup_dir}/${site_name}-${timestamp}.sql" || return 1
    tar -czf "${backup_dir}/${site_name}-files-${timestamp}.tar.gz" . || return 1
    echo "Backup completed for ${site_name}"
}

<em># Use the function</em>
backup_wordpress /var/www/siteA /backups
backup_wordpress /var/www/siteB /backups
backup_wordpress /var/www/siteC /backups
</code></pre>



<p>One function, multiple uses. Change the backup logic once, and all three sites benefit.</p>



<h3 class="wp-block-heading" id="basic-function-syntax-basic-syntax">Basic Function Syntax {#basic-syntax}</h3>



<p>Bash functions can be defined in two ways:</p>



<h4 class="wp-block-heading" id="method-1-using-the-function-keyword">Method 1: Using the&nbsp;<code>function</code>&nbsp;Keyword</h4>



<pre class="wp-block-code"><code>function my_function() {
    echo "Hello from my function"
}
</code></pre>



<h4 class="wp-block-heading" id="method-2-without-the-function-keyword-posix-compliant">Method 2: Without the&nbsp;<code>function</code>&nbsp;Keyword (POSIX-compliant)</h4>



<pre class="wp-block-code"><code>my_function() {
    echo "Hello from my function"
}
</code></pre>



<p>Both work identically. Method 2 is more portable and preferred for production scripts.</p>



<h4 class="wp-block-heading" id="calling-functions">Calling Functions</h4>



<p>Simply use the function name:</p>



<pre class="wp-block-code"><code>my_function  <em># Calls the function</em>
</code></pre>



<h4 class="wp-block-heading" id="example-simple-wordpress-function">Example: Simple WordPress Function</h4>



<pre class="wp-block-code"><code>#!/bin/bash

<em># Function to check WordPress version</em>
check_wp_version() {
    wp core version
}

<em># Call it</em>
check_wp_version
</code></pre>



<p><strong>Output:</strong></p>



<pre class="wp-block-code"><code>6.4.2
</code></pre>



<h3 class="wp-block-heading" id="parameter-handling-in-functions-parameters">Parameter Handling in Functions</h3>



<p>Functions accept parameters just like scripts. Parameters are accessed using&nbsp;<code>$1</code>,&nbsp;<code>$2</code>,&nbsp;<code>$3</code>, etc.</p>



<h4 class="wp-block-heading" id="basic-parameters">Basic Parameters</h4>



<pre class="wp-block-code"><code>greet_user() {
    local name=$1
    echo "Hello, ${name}!"
}

greet_user "John"  <em># Output: Hello, John!</em>
</code></pre>



<h4 class="wp-block-heading" id="multiple-parameters">Multiple Parameters</h4>



<pre class="wp-block-code"><code>update_wordpress() {
    local wp_path=$1
    local backup=$2

    cd "$wp_path" || return 1

    if &#91; "$backup" = "yes" ]; then
        wp db export backup.sql
    fi

    wp core update
}

<em># Usage</em>
update_wordpress /var/www/html yes
</code></pre>



<h4 class="wp-block-heading" id="parameter-variables">Parameter Variables</h4>



<p>Bash provides special variables for working with parameters:</p>



<ul class="wp-block-list">
<li><code>$#</code>&nbsp;&#8211; Number of parameters</li>



<li><code>$@</code>&nbsp;&#8211; All parameters as separate strings</li>



<li><code>$*</code>&nbsp;&#8211; All parameters as single string</li>



<li><code>$1, $2, ...</code>&nbsp;&#8211; Individual parameters</li>
</ul>



<h4 class="wp-block-heading" id="wordpress-example-plugin-update-function">WordPress Example: Plugin Update Function</h4>



<pre class="wp-block-code"><code>update_plugin() {
    local wp_path=$1
    local plugin_name=$2

    echo "Updating plugin: ${plugin_name} at ${wp_path}"
    wp plugin update "$plugin_name" --path="$wp_path"
}

<em># Usage</em>
update_plugin /var/www/html woocommerce
update_plugin /var/www/html yoast-seo
</code></pre>



<h3 class="wp-block-heading" id="return-values-and-exit-codes-return-values">Return Values and Exit Codes</h3>



<p>Bash functions don&#8217;t return values like other programming languages. Instead, they use:</p>



<ol class="wp-block-list">
<li><strong>Exit codes</strong>&nbsp;(0 for success, non-zero for failure)</li>



<li><strong>Echo statements</strong>&nbsp;(output that can be captured)</li>
</ol>



<h4 class="wp-block-heading" id="exit-codes-with-return">Exit Codes with&nbsp;<code>return</code></h4>



<pre class="wp-block-code"><code>check_wordpress_exists() {
    local wp_path=$1

    if &#91; -f "${wp_path}/wp-config.php" ]; then
        return 0  <em># Success</em>
    else
        return 1  <em># Failure</em>
    fi
}

<em># Usage</em>
if check_wordpress_exists /var/www/html; then
    echo "WordPress found!"
else
    echo "WordPress not found"
fi
</code></pre>



<p><strong>Best Practice</strong>: Always return 0 for success, 1+ for errors. This follows Unix conventions and works with&nbsp;<code>if</code>&nbsp;statements.</p>



<h4 class="wp-block-heading" id="returning-values-via-echo">Returning Values via Echo</h4>



<pre class="wp-block-code"><code>get_wordpress_version() {
    local wp_path=$1
    wp core version --path="$wp_path"
}

<em># Capture output</em>
version=$(get_wordpress_version /var/www/html)
echo "WordPress version: ${version}"
</code></pre>



<h4 class="wp-block-heading" id="combining-both-approaches">Combining Both Approaches</h4>



<pre class="wp-block-code"><code>backup_database() {
    local wp_path=$1
    local backup_file=$2

    <em># Perform backup</em>
    if wp db export "$backup_file" --path="$wp_path" 2&gt;/dev/null; then
        echo "$backup_file"  <em># Return filename</em>
        return 0             <em># Success exit code</em>
    else
        echo ""              <em># Return empty string</em>
        return 1             <em># Failure exit code</em>
    fi
}

<em># Usage</em>
if backup_file=$(backup_database /var/www/html "/backups/db.sql"); then
    echo "Backup successful: ${backup_file}"
else
    echo "Backup failed"
fi
</code></pre>



<h3 class="wp-block-heading" id="error-handling-best-practices-error-handling">Error Handling Best Practices</h3>



<p>Production-ready functions need robust error handling. Here&#8217;s how to do it right.</p>



<h4 class="wp-block-heading" id="use-set--e-cautiously">Use&nbsp;<code>set -e</code>&nbsp;Cautiously</h4>



<pre class="wp-block-code"><code>#!/bin/bash
set -e  <em># Exit on any error</em>

<em># This will exit the entire script if wp fails</em>
wp plugin update --all
</code></pre>



<p><strong>Problem</strong>:&nbsp;<code>set -e</code>&nbsp;exits the entire script on first error, which might not be what you want in functions.</p>



<p><strong>Better approach</strong>: Handle errors explicitly in functions.</p>



<h4 class="wp-block-heading" id="check-command-success">Check Command Success</h4>



<pre class="wp-block-code"><code>update_all_plugins() {
    local wp_path=$1

    if ! wp plugin update --all --path="$wp_path"; then
        echo "ERROR: Plugin update failed" &gt;&amp;2
        return 1
    fi

    echo "All plugins updated successfully"
    return 0
}
</code></pre>



<h4 class="wp-block-heading" id="validate-parameters">Validate Parameters</h4>



<pre class="wp-block-code"><code>backup_wordpress() {
    local wp_path=$1
    local backup_dir=$2

    <em># Validate parameters exist</em>
    if &#91; -z "$wp_path" ] || &#91; -z "$backup_dir" ]; then
        echo "ERROR: Missing parameters" &gt;&amp;2
        echo "Usage: backup_wordpress &lt;wp_path&gt; &lt;backup_dir&gt;" &gt;&amp;2
        return 1
    fi

    <em># Validate WordPress directory</em>
    if &#91; ! -f "${wp_path}/wp-config.php" ]; then
        echo "ERROR: Not a WordPress installation: ${wp_path}" &gt;&amp;2
        return 1
    fi

    <em># Validate backup directory</em>
    if &#91; ! -d "$backup_dir" ]; then
        echo "ERROR: Backup directory doesn't exist: ${backup_dir}" &gt;&amp;2
        return 1
    fi

    <em># Perform backup</em>
    <em># ... backup logic here ...</em>
}
</code></pre>



<h4 class="wp-block-heading" id="use-error-messages-to-stderr">Use Error Messages to STDERR</h4>



<p>Send errors to&nbsp;<code>stderr</code>&nbsp;(file descriptor 2) instead of&nbsp;<code>stdout</code>:</p>



<pre class="wp-block-code"><code>log_error() {
    echo "&#91;ERROR] $*" &gt;&amp;2
}

log_info() {
    echo "&#91;INFO] $*"
}

<em># Usage</em>
if ! wp core update; then
    log_error "WordPress core update failed"
    return 1
fi

log_info "WordPress updated successfully"
</code></pre>



<p>This allows users to separate errors from normal output:</p>



<pre class="wp-block-code"><code>./script.sh 2&gt;errors.log  <em># Only errors go to file</em>
./script.sh 2&gt;&amp;1 | grep ERROR  <em># Search errors</em>
</code></pre>



<h3 class="wp-block-heading" id="real-world-wordpress-functions-wordpress-functions">Real-World WordPress Functions {#wordpress-functions}</h3>



<p>Let&#8217;s build production-ready functions you can use immediately.</p>



<h4 class="wp-block-heading" id="function-1-wordpress-site-backup">Function 1: WordPress Site Backup</h4>



<pre class="wp-block-code"><code>#!/bin/bash

backup_wordpress_site() {
    local wp_path=$1
    local backup_dir=$2
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local site_name=$(basename "$wp_path")

    <em># Validate inputs</em>
    if &#91; -z "$wp_path" ] || &#91; -z "$backup_dir" ]; then
        echo "ERROR: Usage: backup_wordpress_site &lt;wp_path&gt; &lt;backup_dir&gt;" &gt;&amp;2
        return 1
    fi

    if &#91; ! -f "${wp_path}/wp-config.php" ]; then
        echo "ERROR: Invalid WordPress path: ${wp_path}" &gt;&amp;2
        return 1
    fi

    <em># Create backup directory if needed</em>
    mkdir -p "$backup_dir"

    <em># Backup database</em>
    local db_file="${backup_dir}/${site_name}_db_${timestamp}.sql"
    echo "Backing up database..."
    if ! wp db export "$db_file" --path="$wp_path" --quiet; then
        echo "ERROR: Database backup failed" &gt;&amp;2
        return 1
    fi

    <em># Compress database</em>
    gzip "$db_file"
    echo "Database backed up: ${db_file}.gz"

    <em># Backup files</em>
    local files_archive="${backup_dir}/${site_name}_files_${timestamp}.tar.gz"
    echo "Backing up files..."
    if ! tar -czf "$files_archive" -C "$(dirname $wp_path)" "$(basename $wp_path)" 2&gt;/dev/null; then
        echo "ERROR: File backup failed" &gt;&amp;2
        return 1
    fi

    echo "Files backed up: ${files_archive}"
    echo "Backup completed successfully"
    return 0
}

<em># Usage</em>
backup_wordpress_site /var/www/html /backups
</code></pre>



<h4 class="wp-block-heading" id="function-2-bulk-plugin-update-with-verification">Function 2: Bulk Plugin Update with Verification</h4>



<pre class="wp-block-code"><code>update_plugins_safe() {
    local wp_path=$1

    <em># Validation</em>
    if &#91; ! -f "${wp_path}/wp-config.php" ]; then
        echo "ERROR: Invalid WordPress path" &gt;&amp;2
        return 1
    fi

    echo "Checking for plugin updates..."
    local updates=$(wp plugin list --update=available --path="$wp_path" --format=count)

    if &#91; "$updates" -eq 0 ]; then
        echo "All plugins are up to date"
        return 0
    fi

    echo "Found ${updates} plugin(s) to update"

    <em># Backup database before updates</em>
    local backup_file="/tmp/pre-update-backup-$(date +%s).sql"
    echo "Creating safety backup..."
    if ! wp db export "$backup_file" --path="$wp_path" --quiet; then
        echo "ERROR: Safety backup failed, aborting" &gt;&amp;2
        return 1
    fi

    echo "Updating plugins..."
    if wp plugin update --all --path="$wp_path"; then
        echo "Plugins updated successfully"
        rm -f "$backup_file"  <em># Clean up backup if successful</em>
        return 0
    else
        echo "ERROR: Plugin update failed" &gt;&amp;2
        echo "Safety backup available at: ${backup_file}"
        return 1
    fi
}

<em># Usage</em>
update_plugins_safe /var/www/html
</code></pre>



<h4 class="wp-block-heading" id="function-3-wordpress-health-check">Function 3: WordPress Health Check</h4>



<pre class="wp-block-code"><code>wordpress_health_check() {
    local wp_path=$1
    local errors=0

    echo "Running WordPress health check for: ${wp_path}"
    echo "=============================================="

    <em># Check 1: WordPress core</em>
    echo -n "WordPress Core: "
    if wp core verify-checksums --path="$wp_path" &amp;&gt;/dev/null; then
        echo "✓ OK"
    else
        echo "✗ FAILED"
        ((errors++))
    fi

    <em># Check 2: Database</em>
    echo -n "Database Connection: "
    if wp db check --path="$wp_path" &amp;&gt;/dev/null; then
        echo "✓ OK"
    else
        echo "✗ FAILED"
        ((errors++))
    fi

    <em># Check 3: Plugin updates</em>
    echo -n "Plugin Updates: "
    local plugin_updates=$(wp plugin list --update=available --path="$wp_path" --format=count)
    if &#91; "$plugin_updates" -eq 0 ]; then
        echo "✓ All up to date"
    else
        echo "⚠ ${plugin_updates} update(s) available"
    fi

    <em># Check 4: Theme updates</em>
    echo -n "Theme Updates: "
    local theme_updates=$(wp theme list --update=available --path="$wp_path" --format=count)
    if &#91; "$theme_updates" -eq 0 ]; then
        echo "✓ All up to date"
    else
        echo "⚠ ${theme_updates} update(s) available"
    fi

    <em># Check 5: Core version</em>
    local wp_version=$(wp core version --path="$wp_path")
    echo "WordPress Version: ${wp_version}"

    echo "=============================================="
    if &#91; $errors -eq 0 ]; then
        echo "Health check passed"
        return 0
    else
        echo "Health check failed with ${errors} error(s)"
        return 1
    fi
}

<em># Usage</em>
wordpress_health_check /var/www/html
</code></pre>



<h3 class="wp-block-heading" id="building-a-function-library-function-library">Building a Function Library {#function-library}</h3>



<p>Create a reusable library that you can source into any WordPress automation script.</p>



<h4 class="wp-block-heading" id="create-the-library-file">Create the Library File</h4>



<pre class="wp-block-code"><code><em># Save as: ~/wp-functions.sh</em>

<em>#!/bin/bash</em>
<em>#</em>
<em># WordPress Automation Function Library</em>
<em># Source this file in your scripts: source ~/wp-functions.sh</em>
<em>#</em>

<em># Color codes for output</em>
RED='\033&#91;0;31m'
GREEN='\033&#91;0;32m'
YELLOW='\033&#91;1;33m'
NC='\033&#91;0m' <em># No Color</em>

<em># Logging functions</em>
log_info() {
    echo -e "${GREEN}&#91;INFO]${NC} $*"
}

log_error() {
    echo -e "${RED}&#91;ERROR]${NC} $*" &gt;&amp;2
}

log_warning() {
    echo -e "${YELLOW}&#91;WARNING]${NC} $*"
}

<em># Check if path is valid WordPress installation</em>
is_wordpress() {
    local wp_path=$1
    &#91; -f "${wp_path}/wp-config.php" ]
}

<em># Get WordPress version</em>
get_wp_version() {
    local wp_path=$1
    wp core version --path="$wp_path" 2&gt;/dev/null
}

<em># Check if plugin is installed</em>
has_plugin() {
    local wp_path=$1
    local plugin_name=$2
    wp plugin is-installed "$plugin_name" --path="$wp_path" 2&gt;/dev/null
}

<em># Safely update WordPress core</em>
safe_core_update() {
    local wp_path=$1

    if ! is_wordpress "$wp_path"; then
        log_error "Not a WordPress installation: ${wp_path}"
        return 1
    fi

    local current_version=$(get_wp_version "$wp_path")
    log_info "Current version: ${current_version}"

    <em># Backup first</em>
    log_info "Creating backup..."
    local backup_file="/tmp/wp-backup-$(date +%s).sql"
    if ! wp db export "$backup_file" --path="$wp_path" --quiet; then
        log_error "Backup failed"
        return 1
    fi

    <em># Update</em>
    log_info "Updating WordPress core..."
    if wp core update --path="$wp_path"; then
        local new_version=$(get_wp_version "$wp_path")
        log_info "Updated from ${current_version} to ${new_version}"
        rm -f "$backup_file"
        return 0
    else
        log_error "Update failed. Backup saved at: ${backup_file}"
        return 1
    fi
}
</code></pre>



<h4 class="wp-block-heading" id="using-the-library">Using the Library</h4>



<p>Create a script that sources the library:</p>



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

<em># Load function library</em>
source ~/wp-functions.sh

<em># Use the functions</em>
log_info "Starting WordPress maintenance..."

if is_wordpress /var/www/html; then
    log_info "WordPress found"
    safe_core_update /var/www/html
else
    log_error "WordPress not found"
    exit 1
fi
</code></pre>



<p>This approach keeps your scripts clean and maintainable. Update the library once, and all scripts benefit.</p>



<h3 class="wp-block-heading" id="advanced-patterns-advanced-patterns">Advanced Patterns {#advanced-patterns}</h3>



<h4 class="wp-block-heading" id="pattern-1-functions-with-named-parameters">Pattern 1: Functions with Named Parameters</h4>



<pre class="wp-block-code"><code>backup_wordpress() {
    <em># Parse named parameters</em>
    local wp_path=""
    local backup_dir=""
    local include_uploads=true

    while &#91;&#91; $# -gt 0 ]]; do
        case $1 in
            --path)
                wp_path="$2"
                shift 2
                ;;
            --backup-dir)
                backup_dir="$2"
                shift 2
                ;;
            --no-uploads)
                include_uploads=false
                shift
                ;;
            *)
                echo "Unknown option: $1" &gt;&amp;2
                return 1
                ;;
        esac
    done

    <em># Use the parameters</em>
    echo "Path: ${wp_path}"
    echo "Backup dir: ${backup_dir}"
    echo "Include uploads: ${include_uploads}"
}

<em># Usage</em>
backup_wordpress --path /var/www/html --backup-dir /backups --no-uploads
</code></pre>



<h4 class="wp-block-heading" id="pattern-2-functions-with-default-parameters">Pattern 2: Functions with Default Parameters</h4>



<pre class="wp-block-code"><code>update_wordpress() {
    local wp_path=${1:-/var/www/html}  <em># Default to /var/www/html</em>
    local backup=${2:-yes}               <em># Default to yes</em>

    echo "Path: ${wp_path}"
    echo "Backup: ${backup}"
}

<em># Call with defaults</em>
update_wordpress

<em># Call with custom values</em>
update_wordpress /var/www/mysite no
</code></pre>



<h4 class="wp-block-heading" id="pattern-3-array-return-values">Pattern 3: Array Return Values</h4>



<pre class="wp-block-code"><code>get_outdated_plugins() {
    local wp_path=$1
    wp plugin list --update=available --path="$wp_path" --field=name
}

<em># Capture into array</em>
mapfile -t plugins &lt; &lt;(get_outdated_plugins /var/www/html)

<em># Loop through results</em>
for plugin in "${plugins&#91;@]}"; do
    echo "Outdated: ${plugin}"
done
</code></pre>



<h3 class="wp-block-heading" id="testing-your-functions-testing">Testing Your Functions {#testing}</h3>



<p>Always test functions before using in production.</p>



<h4 class="wp-block-heading" id="manual-testing-script">Manual Testing Script</h4>



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

source ~/wp-functions.sh

echo "Testing WordPress functions..."
echo "=============================="

<em># Test 1: is_wordpress</em>
echo "Test 1: is_wordpress"
if is_wordpress /var/www/html; then
    echo "✓ PASS"
else
    echo "✗ FAIL"
fi

<em># Test 2: get_wp_version</em>
echo "Test 2: get_wp_version"
version=$(get_wp_version /var/www/html)
if &#91; -n "$version" ]; then
    echo "✓ PASS: Version ${version}"
else
    echo "✗ FAIL"
fi

<em># Add more tests...</em>
</code></pre>



<h4 class="wp-block-heading" id="automated-testing-with-bats">Automated Testing with BATS</h4>



<p>For serious projects, use&nbsp;<a href="https://github.com/bats-core/bats-core">BATS (Bash Automated Testing System)</a>:</p>



<pre class="wp-block-code"><code><em># Install BATS</em>
git clone https://github.com/bats-core/bats-core.git
cd bats-core
./install.sh /usr/local

<em># Create test file: test-wp-functions.bats</em>
<em>#!/usr/bin/env bats</em>

load ~/wp-functions.sh

@test "is_wordpress returns true for valid path" {
    run is_wordpress /var/www/html
    &#91; "$status" -eq 0 ]
}

@test "is_wordpress returns false for invalid path" {
    run is_wordpress /tmp
    &#91; "$status" -eq 1 ]
}

<em># Run tests</em>
bats test-wp-functions.bats
</code></pre>



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



<p>You now know how to write reusable Bash functions for WordPress automation. Here&#8217;s what to learn next:</p>



<h4 class="wp-block-heading" id="related-guides">Related Guides</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Bulletproof Error Handling in Bash Scripts for WP-CLI</a></strong> &#8211; Take error handling to the next level</li>



<li><strong><a href="#">How to Parse Command Line Arguments in WP-CLI Bash Scripts</a></strong> &#8211; Make your functions accept complex parameters</li>



<li><strong><a href="https://file+.vscode-resource.vscode-cdn.net/blog/logging-debugging-wpcli-automation">Professional Logging and Debugging for WP-CLI Automation Scripts</a></strong>&nbsp;&#8211; Add production-grade logging</li>
</ol>



<h4 class="wp-block-heading" id="practice-projects">Practice Projects</h4>



<p><strong>Build a function library</strong>&nbsp;with these functions:</p>



<ul class="wp-block-list">
<li>Database backup and restore</li>



<li>Plugin/theme management</li>



<li>User management</li>



<li>Content import/export</li>



<li>Security hardening</li>
</ul>



<p><strong>Create a WordPress maintenance script</strong>&nbsp;that:</p>



<ul class="wp-block-list">
<li>Uses multiple functions from your library</li>



<li>Accepts command-line arguments</li>



<li>Has proper error handling</li>



<li>Outputs colored logs</li>
</ul>



<h4 class="wp-block-heading" id="join-wpcli-mastery">Join WPCLI Mastery</h4>



<p>Want to master WordPress automation with battle-tested patterns and real-world projects?</p>



<p><strong><a href="/#pricing">Join the WPCLI Mastery waitlist</a></strong> and get:</p>



<ul class="wp-block-list">
<li>Free WordPress backup automation script (production-ready functions included)</li>



<li>Access to complete function library</li>



<li>Early bird course pricing ($99 vs $199)</li>
</ul>



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



<p>Bash functions transform messy WordPress automation scripts into clean, maintainable, professional code. The patterns you learned here—parameter validation, error handling, return values—are the foundation of production-ready automation.</p>



<p><strong>Key takeaways:</strong></p>



<ul class="wp-block-list">
<li>Functions eliminate code duplication</li>



<li>Always validate parameters</li>



<li>Use return codes (0 = success, 1+ = failure)</li>



<li>Handle errors explicitly</li>



<li>Build a reusable function library</li>



<li>Test your functions before production use</li>
</ul>



<p>Start building your function library today. Every reusable function you write saves time on every future script.</p>



<p><strong>Ready to build advanced WordPress automation?</strong> Check out our guide on <a href="#">automating WordPress backups with WP-CLI</a>, which uses these function patterns in a complete project.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><strong>Questions about Bash functions for WordPress?</strong>&nbsp;Drop a comment below!</p>



<p><strong>Found this helpful?</strong>&nbsp;Share it with other WordPress developers learning automation.</p>
<p>The post <a href="https://wpclimastery.com/blog/writing-reusable-bash-functions-for-wordpress-automation/">Writing Reusable Bash Functions for WordPress Automation</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpclimastery.com/blog/writing-reusable-bash-functions-for-wordpress-automation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
