do/commands/find
2025-10-10 14:49:06 -04:00

412 lines
No EOL
17 KiB
Bash
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ----------------------------------------------------
# Finds files that have been recently modified.
# ----------------------------------------------------
function find_recent_files() {
local days="${1:-1}" # Default to 1 day if no argument is provided
# Validate that the input is a number
if ! [[ "$days" =~ ^[0-9]+$ ]]; then
echo "❌ Error: Please provide a valid number of days." >&2
echo "Usage: _do find recent-files <days>" >&2
return 1
fi
echo "🔎 Searching for files modified in the last $days day(s)..."
echo
# Check the operating system to use the correct `find` command syntax.
# The `-printf` option is not available on macOS/BSD `find`.
if [[ "$(uname)" == "Darwin" ]]; then
# On macOS, use -exec with `stat` for formatted, sortable output.
# -f "%Sm %N" formats the output: Modification time, then file name.
# -t "%Y-%m-%d %H:%M:%S" specifies the timestamp format for sorting.
find . -type f -mtime "-${days}" -exec stat -f "%Sm %N" -t "%Y-%m-%d %H:%M:%S" {} + | sort -r
else
# On Linux, the more efficient -printf option is available.
find . -type f -mtime "-${days}" -printf "%TY-%Tm-%Td %TH:%M:%S %p\n" | sort -r
fi
if [ $? -ne 0 ]; then
echo "❌ Error: The 'find' command failed to execute." >&2
return 1
fi
}
# ----------------------------------------------------
# Identifies plugins that may be slowing down WP-CLI command execution.
# ----------------------------------------------------
function find_slow_plugins() {
local page_to_check="${1}"
_get_wp_execution_time() {
local output
output=$("$WP_CLI_CMD" "$@" --debug 2>&1)
echo "$output" | perl -ne '/Debug \(bootstrap\): Running command: .+\(([^s]+s)/ && print $1'
}
if ! setup_wp_cli; then echo "❌ Error: WP-CLI (wp command) not found." >&2; return 1; fi
if ! "$WP_CLI_CMD" core is-installed --quiet; then echo "❌ Error: This does not appear to be a WordPress installation." >&2; return 1; fi
local base_command_args=("plugin" "list")
local skip_argument="--skip-plugins"
local description="wp plugin list --debug"
if [ -n "$page_to_check" ]; then
echo "🚀 WordPress Plugin Performance Test for page: '$page_to_check' 🚀"
description="wp render \"$page_to_check\" --debug"
# Check for wp render and install if missing
if ! "$WP_CLI_CMD" help render &> /dev/null; then
echo " 'wp render' command not found. Installing 'render-command' plugin..."
if ! "$WP_CLI_CMD" plugin install https://github.com/austinginder/render-command/releases/latest/download/render-command.zip --activate --force; then
echo "❌ Error: Failed to install 'render-command' plugin. Aborting." >&2
return 1
fi
echo "✅ 'render-command' plugin installed successfully."
fi
# Update command variables to use 'wp render'
base_command_args=("render" "$page_to_check")
skip_argument="--without-plugin"
else
echo "🚀 WordPress Plugin Performance Test 🚀"
fi
echo "This script measures the execution time of '$description' under various conditions."
echo ""
echo "📋 Initial Baseline Measurements for '$description':"
local base_time_s
printf " ⏳ Measuring base time (ALL plugins & theme active)... "
base_time_s=$(_get_wp_execution_time "${base_command_args[@]}")
if [[ -z "$base_time_s" ]]; then
echo "❌ Error: Could not measure base execution time." >&2
return 1
fi
echo "Base time: $base_time_s"
echo ""
local active_plugins=()
while IFS= read -r line; do
active_plugins+=("$line")
done < <("$WP_CLI_CMD" plugin list --field=name --status=active)
if [[ ${#active_plugins[@]} -eq 0 ]]; then
echo " No active plugins found to test."
return 0
fi
echo "📊 Measuring impact of individual plugins (compared to '${base_time_s}' base time):"
echo "A larger positive 'Impact' suggests the plugin contributes more to the load time of this specific WP-CLI command."
echo "---------------------------------------------------------------------------------"
printf "%-40s | %-15s | %-15s\n" "Plugin Skipped" "Time w/ Skip" "Impact (Base-Skip)"
echo "---------------------------------------------------------------------------------"
local results=()
for plugin in "${active_plugins[@]}"; do
# Skip the render-command plugin itself when using the render method
if [[ -n "$page_to_check" && "$plugin" == "render-command" ]]; then
continue
fi
local time_with_skip_s
time_with_skip_s=$(_get_wp_execution_time "${base_command_args[@]}" "${skip_argument}=$plugin")
if [[ -n "$time_with_skip_s" ]]; then
local diff_s
diff_s=$(awk -v base="${base_time_s%s}" -v skip="${time_with_skip_s%s}" 'BEGIN { printf "%.3f", base - skip }')
local impact_sign=""
if [[ $(awk -v diff="$diff_s" 'BEGIN { print (diff > 0) }') -eq 1 ]]; then
impact_sign="+"
fi
results+=("$(printf "%.3f" "$diff_s")|$plugin|$time_with_skip_s|${impact_sign}${diff_s}s")
else
results+=("0.000|$plugin|Error|Error measuring")
fi
done
local sorted_results=()
while IFS= read -r line; do
sorted_results+=("$line")
done < <(printf "%s\n" "${results[@]}" | sort -t'|' -k1,1nr)
for result_line in "${sorted_results[@]}"; do
local p_name
p_name=$(echo "$result_line" | cut -d'|' -f2)
local t_skip
t_skip=$(echo "$result_line" | cut -d'|' -f3)
local i_str
i_str=$(echo "$result_line" | cut -d'|' -f4)
printf "%-40s | %-15s | %-15s\n" "$p_name" "$t_skip" "$i_str"
done
echo "---------------------------------------------------------------------------------"
echo ""
echo "✅ Test Complete"
echo "💡 Note: This measures impact on a specific WP-CLI command. For front-end or"
echo " admin profiling, consider using a plugin like Query Monitor or New Relic."
echo ""
}
# ----------------------------------------------------
# Detects plugins that are active but hidden from the standard plugin list.
# ----------------------------------------------------
function find_hidden_plugins() {
# --- Pre-flight Checks ---
if ! setup_wp_cli; then echo "❌ Error: WP-CLI not found." >&2; return 1; fi
if ! "$WP_CLI_CMD" core is-installed --quiet; then echo "❌ Error: This does not appear to be a WordPress installation." >&2; return 1; fi
if ! setup_gum; then return 1; fi
echo "🚀 Checking for hidden WordPress plugins..."
# Get the standard list of active plugins
local active_plugins
active_plugins=$("$WP_CLI_CMD" plugin list --field=name --status=active)
# Get the "raw" list of active plugins by skipping themes and other plugins
local active_plugins_raw
active_plugins_raw=$("$WP_CLI_CMD" plugin list --field=name --status=active --skip-themes --skip-plugins)
local regular_count
regular_count=$(echo "$active_plugins" | wc -l | xargs)
local raw_count
raw_count=$(echo "$active_plugins_raw" | wc -l | xargs)
# Compare the counts of the two lists.
if [[ "$regular_count" == "$raw_count" ]]; then
echo "✅ No hidden plugins detected. The standard and raw plugin lists match ($regular_count plugins)."
return 0
fi
# If the counts differ, find the plugins that are in the raw list but not the standard one.
echo "⚠️ Found a discrepancy between plugin lists!"
echo " - Standard list shows: $regular_count active plugins."
echo " - Raw list shows: $raw_count active plugins."
echo
# Use 'comm' to find lines unique to the raw list.
local hidden_plugins
hidden_plugins=$(comm -13 <(echo "$active_plugins" | sort) <(echo "$active_plugins_raw" | sort))
if [ -z "$hidden_plugins" ]; then
echo " Could not isolate the specific hidden plugins, but a discrepancy exists."
else
echo "--- Found Hidden Plugin(s) ---"
# Loop through each hidden plugin and get its details
while IFS= read -r plugin; do
if [ -z "$plugin" ]; then continue; fi
"$GUM_CMD" log --level warn "Details for: $plugin"
# Get plugin details in CSV format and pipe to gum for a clean table printout.
"$WP_CLI_CMD" plugin get "$plugin" --skip-plugins --skip-themes --format=csv | \
"$GUM_CMD" table --separator "," --widths=15,0 --print
echo
done <<< "$hidden_plugins"
echo "💡 These plugins are active but may be hidden from the admin view or standard WP-CLI list."
echo " Common offenders are management plugins (like ManageWP's 'worker') or potentially malicious code."
fi
}
# ----------------------------------------------------
# Scans for potential malware and verifies WordPress core/plugin integrity.
# ----------------------------------------------------
function find_malware() {
# --- Pre-flight Checks ---
if ! setup_wp_cli; then echo "❌ Error: WP-CLI not found." >&2; return 1; fi
if ! "$WP_CLI_CMD" core is-installed --quiet; then echo "❌ Error: This does not appear to be a WordPress installation." >&2; return 1; fi
if ! command -v grep &> /dev/null; then echo "❌ Error: 'grep' command not found." >&2; return 1; fi
if ! setup_gum; then return 1; fi
echo "🚀 Starting malware scan..."
echo "This process will check for suspicious code patterns and verify core/plugin file integrity."
echo
# --- 1. Hunt for suspicious PHP code ---
echo "--- Step 1/3: Searching for suspicious PHP code patterns... ---"
local suspicious_patterns=(
'eval(base64_decode('
'eval(gzinflate('
'eval(gzuncompress('
'eval(str_rot13('
'preg_replace.*\/e'
'create_function'
'FilesMan'
'c99shell'
'r57shell'
'shell_exec('
'passthru('
'system('
'phpinfo('
'assert('
)
local found_suspicious_files=false
local combined_pattern
combined_pattern=$(IFS='|'; echo "${suspicious_patterns[*]}")
local search_results
search_results=$(grep -rn --include='*.php' -iE "$combined_pattern" . 2>/dev/null)
if [ -n "$search_results" ]; then
echo "⚠️ Found potentially malicious code in the following files:"
echo "-----------------------------------------------------"
echo "$search_results"
echo "-----------------------------------------------------"
echo "💡 Review these files carefully. They may contain legitimate code that matches these patterns."
found_suspicious_files=true
else
echo "✅ No suspicious code patterns found."
fi
echo
# --- 2. Verify WordPress Core Checksums ---
echo "--- Step 2/3: Verifying WordPress core file integrity... ---"
if ! "$WP_CLI_CMD" core verify-checksums --skip-plugins --skip-themes; then
echo "⚠️ WordPress core verification failed. The files listed above may have been modified."
else
echo "✅ WordPress core files verified successfully."
fi
echo
# --- 3. Verify Plugin Checksums ---
echo "--- Step 3/3: Verifying plugin file integrity (from wordpress.org)... ---"
local stderr_file_plugin
stderr_file_plugin=$(mktemp)
local plugin_csv_data
plugin_csv_data=$("$WP_CLI_CMD" plugin verify-checksums --all --format=csv --skip-plugins --skip-themes --quiet 2> "$stderr_file_plugin")
local plugin_checksum_status=$?
local plugin_summary_error
plugin_summary_error=$(cat "$stderr_file_plugin")
rm "$stderr_file_plugin"
if [ $plugin_checksum_status -ne 0 ]; then
echo "⚠️ Plugin verification encountered an error or found mismatches."
# Check if there is any CSV data to display
if [[ -n "$plugin_csv_data" ]]; then
echo "$plugin_csv_data" | "$GUM_CMD" table --separator "," --print
fi
# Display the summary error if it exists
if [ -n "$plugin_summary_error" ]; then
echo "$plugin_summary_error"
fi
echo "💡 This may include plugins not in the wordpress.org directory (premium plugins) or modified files."
else
echo "✅ All plugins from wordpress.org verified successfully."
fi
echo
echo "✅ Malware scan complete."
}
# ----------------------------------------------------
# Finds outdated or invalid PHP opening tags in PHP files.
# ----------------------------------------------------
function find_outdated_php_tags() {
local search_dir="${1:-.}"
# Ensure the search directory ends with a slash for consistency
if [[ "${search_dir: -1}" != "/" ]]; then
search_dir+="/"
fi
if [ ! -d "$search_dir" ]; then
echo "❌ Error: Directory '$search_dir' not found." >&2
return 1
fi
echo "🚀 Searching for outdated PHP tags in '${search_dir}'..."
echo "This can take a moment for large directories."
echo
# This new, more portable method first finds all lines with '<?',
# then filters out the lines containing valid tags like '<?php', '<?=', or '<?xml'.
# This avoids reliance on potentially unsupported 'grep -P' features.
local initial_results
initial_results=$(grep --include="*.php" --line-number --recursive '<?' "$search_dir" 2>/dev/null \
| grep -v -F -e '<?php' -e '<?=' -e '<?xml' \
| grep --color=always -e '<?' -e '$^'
)
# Filter out common false positives from comments, strings, etc.
local found_tags
found_tags=$(echo "$initial_results" \
| grep -v -F -e "strpos(" -e "str_replace(" \
| grep -v -E "^[^:]*:[^:]*:\s*(\*|//|#)|'\<\?'|\"\<\?\"" \
)
if [ -z "$found_tags" ]; then
echo "✅ No outdated PHP tags were found (after filtering common false positives)."
else
echo "⚠️ Found potentially outdated PHP tags in the following files:"
echo "-----------------------------------------------------"
# The output from grep is already well-formatted.
echo "$found_tags"
echo "-----------------------------------------------------"
# Use single quotes instead of backticks to prevent command execution.
echo "Recommendation: Replace all short tags like '<?' with the full '<?php' tag."
fi
}
# ----------------------------------------------------
# Identifies a plugin that may be causing WP-CLI commands to hang or time out.
# ----------------------------------------------------
function find_stuck_plugin() {
# --- Pre-flight Checks ---
if ! setup_wp_cli; then echo " Error: WP-CLI not found." >&2; return 1; fi
if ! "$WP_CLI_CMD" core is-installed --quiet; then echo " Error: This does not appear to be a WordPress installation." >&2; return 1; fi
if ! command -v timeout &> /dev/null; then echo " Error: 'timeout' command not found. This is required to detect hanging processes." >&2; return 1; fi
# --- Baseline Check ---
echo " Performing a baseline check to confirm WP-CLI is hanging..."
timeout 3s "$WP_CLI_CMD" option get home >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo " Baseline check successful. WP-CLI doesn't appear to be hanging."
return 0
else
echo " Baseline check timed out. Confirmed that WP-CLI is hanging, proceeding with test."
fi
echo
echo " 🚀 Starting stuck plugin check..."
echo " This will test each active plugin to see if skipping it allows WP-CLI to respond quickly."
echo
# --- List of active plugins to test ---
local plugins
plugins=$("$WP_CLI_CMD" plugin list --field=name --status=active --skip-plugins)
if [ -z "$plugins" ]; then
echo " No active plugins found to test."
return 0
fi
# --- Loop through each plugin ---
for plugin in $plugins; do
echo -n " Testing with '$plugin' skipped..."
# Run the WP-CLI command with a 3-second timeout.
# We silence the output since we only care if it succeeds.
timeout 3s "$WP_CLI_CMD" option get home --skip-plugins="$plugin" >/dev/null 2>&1
# Check the exit code of the last command
if [ $? -eq 0 ]; then
# An exit code of 0 means the command completed successfully within the time limit.
echo " ✅ SUCCESS!"
echo "--------------------------------------------------------"
echo " Found the culprit! The site responded quickly when skipping:"
echo " ➡️ $plugin"
echo "--------------------------------------------------------"
return 0
else
# A non-zero exit code means it timed out or failed.
echo " ❌ Timeout."
fi
done
echo "--------------------------------------------------------"
echo " ⏹️ Finished testing all plugins. No single plugin could be identified as the culprit."
}