WordPress w terminalu serwera – automatyzacja, audyt i administracja

Opublikowano: 30 marca 2026 · Autor: Marcin Szewczyk-Wilgan

Panel administracyjny WordPressa i WP-CLI to narzędzia, po które sięgasz w pierwszej kolejności. Ale są sytuacje, w których żadne z nich nie wystarczy – masowa zamiana domeny po migracji w kilkudziesięciu plikach motywu, szukanie backdoora w tysiącach plików PHP po włamaniu, analiza logów serwera pod kątem ataków brute force czy audyt kodu motywu przed konwersją na motyw blokowy. W takich sytuacjach cztery komendy terminala – grep, find, sedawk – pozwalają w kilka sekund zrobić to, co ręcznie zajęłoby godziny. W tym artykule znajdziesz 85 gotowych do użycia poleceń pogrupowanych tematycznie – od bezpieczeństwa i migracji, przez optymalizację i analizę logów, po pracę z motywami i masowe operacje na plikach.

1. Bezpieczeństwo i audyt po włamaniu

Włamanie na stronę WordPress to scenariusz, w którym liczy się czas i precyzja. Musisz szybko ustalić, które pliki zostały zmodyfikowane, gdzie ukryto złośliwy kod i jakim wektorem dostał się atakujący. Ręczne przeglądanie tysięcy plików w wp-content/ nie wchodzi w grę. Poniższe komendy pozwalają w kilka sekund przeskanować całą instalację pod kątem typowych oznak włamania. Więcej o wektorach ataków i wielowarstwowej ochronie w artykule Bezpieczeństwo WordPress w 2025/2026.

Pliki PHP zmodyfikowane w ciągu ostatnich 24 godzin – pierwsze co sprawdzasz po podejrzeniu włamania:

find wp-content/ -name "*.php" -mtime -1

Szukaj eval() – typowy marker malware – prawie każdy backdoor WordPress używa eval() do wykonania dynamicznego kodu:

grep -rn "eval(" wp-content/ --include="*.php"

Zakodowany base64 – drugi najczęstszy wektor: atakujący kodują payload w base64, żeby uniknąć wykrycia:

grep -rl "base64_decode" wp-content/ --include="*.php"

Pliki z uprawnieniami 777 – otwarte drzwi na oścież. Żaden plik w instalacji WordPress nie powinien mieć pełnych uprawnień:

find . -type f -perm 0777

Masowe ustawienie poprawnych uprawnień – 644 dla plików, 755 dla katalogów:

find . -type f -exec chmod 644 {} + find . -type d -exec chmod 755 {} +

Pliki o podejrzanie długich nazwach – backdoory często mają losowe, wieloznakowe nazwy:

find wp-content/ -name "*.php" | awk '{ if (length($0) > 100) print }'

Pliki PHP w katalogu uploads – nie powinno ich tam być. Jeśli są – to prawie na pewno malware:

find wp-content/uploads/ -name "*.php"

Ukryte pliki (zaczynające się od kropki) – atakujący chowają skrypty w plikach typu .backdoor.php lub .htaccess z przekierowaniami:

find wp-content/ -name ".*" -type f

Funkcje shell backdoorówshell_exec, passthru, system() pozwalają wykonywać komendy systemowe z poziomu PHP:

grep -rln "shell_exec\|passthru\|system(" wp-content/ --include="*.php"

Iniekcje iframe w motywach – popularna metoda przekierowywania użytkowników na złośliwe strony:

grep -rn "<iframe" wp-content/themes/ --include="*.php"

Include/require z zewnętrznych URL-i – legalny kod WordPress nie pobiera plików z internetu przez include:

grep -rn "include\|require" wp-content/ --include="*.php" | grep "http"

Pliki PHP większe niż 1 MB – nietypowy rozmiar dla pliku WordPress; warto sprawdzić co w środku:

find wp-content/ -name "*.php" -size +1M

Szukaj $_GET, $_POST, $_REQUEST bezpośrednio w motywach – potencjalne punkty wejścia dla ataków injection:

grep -rn "\$_GET\|\$_POST\|\$_REQUEST" wp-content/themes/ --include="*.php"

Szukaj file_put_contentsfile_get_contents – funkcje do zapisu/odczytu plików, często nadużywane przez malware:

grep -rn "file_put_contents\|file_get_contents" wp-content/ --include="*.php" | grep -v "vendor/"

2. Migracja i zmiana domeny

Migracja WordPressa na nowy serwer lub zmiana domeny to moment, w którym łatwo o przeoczenie. Hardkodowane URL-e starej domeny mogą siedzieć w plikach PHP motywu, arkuszach CSS, dumpach SQL, a nawet w plikach .htaccess. WP-CLI i wtyczki migracyjne obsługują bazę danych (łącznie z serializowanymi danymi), ale pliki motywu, wtyczek i konfiguracyjne trzeba przeszukać i poprawić ręcznie. Cały proces krok po kroku opisujemy w przewodniku Migracja WordPress na nowy serwer.

Znajdź wszystkie wystąpienia starej domeny w plikach – punkt wyjścia każdej migracji:

grep -rl "stara-domena\.pl" wp-content/

Policz wystąpienia per plik – żebyś wiedział, gdzie jest najwięcej roboty:

grep -rc "stara-domena\.pl" wp-content/ | awk -F: '$2 > 0' | sort -t: -k2 -rn

Zamień domenę we wszystkich plikach PHP motywu:

find wp-content/themes/ -name "*.php" -exec sed -i 's/stara-domena\.pl/nowa-domena\.pl/g' {} +

Zamień domenę w dumpie SQL (plain text – nie obsługuje serializacji, do tego użyj WP-CLI search-replace):

sed -i 's|https://stara-domena.pl|https://nowa-domena.pl|g' dump.sql

Zamień prefiks tabel w dumpie SQL:

sed -i 's/wp_/wp_klient_/g' dump.sql

Zamień HTTP na HTTPS we wszystkich plikach CSS:

find wp-content/themes/ -name "*.css" -exec sed -i 's|http://|https://|g' {} +

Znajdź hardkodowane URL-e HTTP (bez S) w motywach – mieszane treści (mixed content) to częsty problem po przejściu na SSL:

grep -rn "http://" wp-content/themes/ --include="*.php" --include="*.css"

Znajdź hardkodowane ścieżki absolutne do starego serwera:

grep -rn "/home/staryuser/public_html" wp-content/ --include="*.php"

Zamień ścieżki absolutne po przeniesieniu:

find wp-content/ -name "*.php" -exec sed -i 's|/home/staryuser/public_html|/var/www/html|g' {} +

Zamień ścieżki do uploads po zmianie struktury:

find . -name "*.php" -exec sed -i 's|/uploads/2023/|/uploads/2025/|g' {} +

Znajdź pozostałości po starej domenie w plikach JS:

grep -rn "stara-domena\.pl" wp-content/ --include="*.js"

3. Optymalizacja i porządkowanie

Z czasem instalacja WordPressa obrasta zbędnymi plikami – nieużywane motywy, osierocone pliki tłumaczeń, duplikaty obrazków, martwe pliki CSS i JS. Katalog uploads/ rośnie z miesiąca na miesiąc, a nikt nie sprawdza, ile miejsca zajmują pliki sprzed lat. Poniższe komendy pomogą Ci zrobić porządek. Jeśli szukasz pełnej strategii przyspieszania WordPressa, zobacz usługę optymalizacji i artykuł Optymalizacja Core Web Vitals.

20 największych plików w uploads – wiesz, co optymalizować w pierwszej kolejności:

find wp-content/uploads/ -type f -exec du -h {} + | sort -rh | head -20

Waga katalogów uploads per rok:

du -sh wp-content/uploads/20*/ | sort -rh

Policz obrazki PNG/JPG czekające na konwersję do WebP:

find wp-content/uploads/ \( -name "*.png" -o -name "*.jpg" \) | wc -l

Znajdź obrazki JPG bez odpowiednika WebP:

find wp-content/uploads/ -name "*.jpg" | while read f; do [ ! -f "${f%.jpg}.webp" ] && echo "$f" done

Usuń puste katalogi po czyszczeniu motywu:

find wp-content/themes/stary-motyw/ -type d -empty -delete

Policz linie kodu PHP w motywie (bez pustych i komentarzy):

find wp-content/themes/motyw/ -name "*.php" -exec cat {} + \ | awk 'NF && !/^[[:space:]]*(\/\/|\/\*|\*)/' | wc -l

Znajdź pliki CSS/JS niezmieniane od roku – kandydaci na martwy kod:

find wp-content/themes/ \( -name "*.css" -o -name "*.js" \) -mtime +365

Znajdź duplikaty plików po MD5:

find wp-content/uploads/ -type f -exec md5sum {} + | sort | awk 'a[$1]++{print}'

Pliki CSS większe niż 100 KB – kandydaci do podziału lub minifikacji:

find wp-content/themes/ -name "*.css" -size +100k

Wylistuj wszystkie załadowane fonty w CSS motywu:

grep -rh "@font-face\|woff2\|woff" wp-content/themes/ --include="*.css" | sort -u

Znajdź nieużywane pliki tłumaczeń (.mo) – wtyczka usunięta, ale jej pliki językowe zostały:

find wp-content/languages/plugins/ -name "*.mo" | while read f; do plugin=$(basename "$f" | sed 's/-[a-z]\{2\}_[A-Z]\{2\}.mo//') [ ! -d "wp-content/plugins/$plugin" ] && echo "Orphan: $f" done

Policz liczbę plików per wtyczkę – rozbudowane wtyczki to potencjalny problem wydajnościowy:

find wp-content/plugins/ -maxdepth 1 -type d | while read d; do echo "$(find "$d" -type f | wc -l) $d" done | sort -rn | head -15

4. Analiza logów serwera

Logi serwera to kopalnia informacji – jeśli umiesz je czytać. Plik access.log Nginx-a lub Apache zawiera rekord każdego żądania HTTP: adres IP, URL, kod odpowiedzi, user agent. Z kolei slow-query.log MySQL-a pokazuje zapytania, które trwają za długo. Awk i grep pozwalają w kilka sekund wyciągnąć z tych plików konkretne dane. Jeśli potrzebujesz wsparcia przy konfiguracji logowania i monitoringu – oferujemy administrację serwerem na LinuxFreeBSD.

TOP 20 najczęściej odpytywanych URL-i:

awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20

Adresy IP generujące najwięcej błędów 404:

awk '$9 == 404 {print $1}' access.log | sort | uniq -c | sort -rn | head -10

Kto atakuje wp-login.php (próby brute force):

grep "POST /wp-login.php" access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

Ataki na xmlrpc.php – drugi po wp-login.php cel brute force:

grep "xmlrpc.php" access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

Rozkład kodów HTTP – 200/301/404/500:

awk '{print $9}' access.log | sort | uniq -c | sort -rn

Ruch per godzina – wykryj szczyty i anomalie:

awk '{print $4}' access.log | cut -d: -f2 | sort | uniq -c

Requesty do wp-cron.php per dzień – za częste wywołania mogą obciążać serwer:

grep "wp-cron.php" access.log | awk '{print $4}' | cut -d: -f1 | sort | uniq -c

User agenty skanujące podatności:

grep -i "sqlmap\|nikto\|nmap\|wpscan\|dirbuster" access.log | awk '{print $1}' | sort -u

Najwolniejsze zapytania MySQL z slow query log:

awk '/^# Query_time/{time=$3} /^SELECT|^UPDATE/{print time, $0}' slow-query.log \ | sort -rn | head -10

Próby dostępu do wp-config.php (próba wycieku danych konfiguracyjnych):

grep "wp-config" access.log | awk '{print $1, $7, $9}'

Policz unikalne adresy IP per dzień:

awk '{print $4, $1}' access.log | cut -d: -f1 | sort -u | cut -d' ' -f1 | uniq -c | sort -rn

Requesty zwracające błąd 500 (Internal Server Error):

awk '$9 == 500 {print $4, $7}' access.log | head -20

5. Praca z motywami i konwersja

Audyt kodu motywu przed wdrożeniem, konwersja z motywu klasycznego na motyw blokowy (FSE), szukanie deprecated funkcji, sprawdzenie co motyw ładuje i jakich hooków używa – to zadania, przy których grep jest niezastąpiony. Zamiast przeklikiwać się przez dziesiątki plików PHP, w kilka sekund wyciągniesz z motywu wszystkie add_action, add_filter, wp_enqueue_script, shortcody i hardkodowane kolory. Kryteria wyboru motywu WordPress omawiamy w osobnym artykule.

Deprecated funkcje WordPress w motywiequery_posts, create_function, mysql_query:

grep -rn "query_posts\|create_function\|mysql_query\|ereg(" wp-content/themes/ --include="*.php"

Wszystkie hooki add_actionadd_filter w motywie:

grep -rh "add_action\|add_filter" wp-content/themes/motyw/ --include="*.php" | sort

Wyciągnij same nazwy hooków:

grep -rohP "(add_action|add_filter)\(\s*['\"](\K[^'\"]+)" wp-content/themes/motyw/ | sort -u

Template tagi motywu – get_header, get_footer, get_template_part:

grep -rn "get_header\|get_footer\|get_sidebar\|get_template_part" wp-content/themes/motyw/

Policz ile razy każdy template part jest używany:

grep -roh "get_template_part([^)]*)" wp-content/themes/motyw/ | sort | uniq -c | sort -rn

Co motyw ładuje – wp_enqueue_script i wp_enqueue_style:

grep -rn "wp_enqueue_script\|wp_enqueue_style" wp-content/themes/motyw/ --include="*.php"

Shortcodes użyte w eksporcie XML bazy danych:

grep -oP '\[\w+' export.xml | sort | uniq -c | sort -rn

Hardkodowane kolory w CSS – do wymiany na zmienne CSS:

grep -oP '#[0-9a-fA-F]{3,6}' wp-content/themes/motyw/style.css | sort | uniq -c | sort -rn

Inline style w szablonach PHP – do przeniesienia do arkusza CSS:

grep -rn 'style="' wp-content/themes/motyw/ --include="*.php" | wc -l

Zarejestrowane sidebary i widżety – ważne przy konwersji na motyw blokowy:

grep -rn "register_sidebar\|register_widget" wp-content/themes/motyw/

Zamień tag Google Analytics we wszystkich szablonach:

find wp-content/themes/ -name "*.php" -exec sed -i 's/UA-XXXXXXX-X/G-XXXXXXXXXX/g' {} +

Custom post types i taksonomie zarejestrowane w motywie (powinny być w wtyczce):

grep -rn "register_post_type\|register_taxonomy" wp-content/themes/ --include="*.php"

Bezpośrednie zapytania SQL w motywie – powinny używać $wpdb->prepare():

grep -rn "\$wpdb->query\|\$wpdb->get_" wp-content/themes/ --include="*.php" | grep -v "prepare"

6. Sitemap, SEO i struktura

Techniczna strona SEO wymaga regularnych audytów – czy wszystkie strony mają meta description, czy sitemap zawiera właściwe URL-e, czy pliki .htaccess nie blokują indeksowania. Poniższe komendy pozwalają szybko przeskanować pliki pod kątem brakujących elementów SEO. Pełny przewodnik po strukturze URL, sitemapach i danych strukturalnych znajdziesz w artykule Techniczne SEO WordPress.

Wyciągnij wszystkie URL-e z sitemap.xml:

awk -F'[<>]' '/<loc>/{print $3}' sitemap.xml

Policz URL-e w sitemap:

grep -c "<loc>" sitemap.xml

Znajdź pliki .htaccess we wszystkich podkatalogach:

find . -name ".htaccess" -type f

Usuń BOM (Byte Order Mark) z plików PHP – powoduje problemy z nagłówkami HTTP:

find . -name "*.php" -exec sed -i '1s/^\xEF\xBB\xBF//' {} +

Sprawdź, które pliki HTML nie mają meta description:

find . -name "*.html" | while read f; do grep -qL 'meta name="description"' "$f" && echo "Brak: $f" done

Wyciągnij title ze wszystkich plików HTML:

grep -ohP '<title>\K[^<]+' *.html

Porównaj URL-e w sitemap z rzeczywistymi plikami:

awk -F'[<>]' '/<loc>/{print $3}' sitemap.xml | while read url; do path=$(echo "$url" | sed 's|https://domena.pl||') [ ! -f ".$path" ] && [ ! -f ".$path/index.html" ] && echo "404: $url" done

Znajdź strony bez tagu canonical:

find . -name "*.html" | while read f; do grep -qL 'rel="canonical"' "$f" && echo "Brak canonical: $f" done

7. Bazy danych i WP-CLI

Dump SQL bazy danych WordPress to plik, który potrafi mieć setki megabajtów. Awk i grep pozwalają szybko wyciągnąć z niego informacje bez importowania do MySQL-a – rozmiar tabel, listę użytkowników, liczbę wpisów per typ czy obciążenie tabeli wp_options. Więcej o czyszczeniu i tuningu bazy w artykule Optymalizacja bazy danych WordPress. Potrzebujesz pomocy z administracją MySQL lub PostgreSQL? Zajmujemy się tym na co dzień.

Rozmiar tabel w dumpie SQL (przybliżony, po wielkości INSERT-ów):

awk '/^INSERT INTO/{gsub(/`/,"",$3); size[$3]+=length($0)} END{for(t in size) print int(size[t]/1024)"KB", t}' dump.sql \ | sort -rn | head -20

Policz wpisy per typ posta w eksporcie XML:

grep -oP '<wp:post_type>\K[^<]+' export.xml | sort | uniq -c | sort -rn

Wyciągnij listę adresów e-mail użytkowników z dumpa:

grep "INSERT INTO.*wp_users" dump.sql | grep -oP "'[^']*@[^']*'" | sort -u

Policz rekordy autoload w wp_options – nadmiar autoload to częsta przyczyna wolnego TTFB:

grep -c "'yes'" dump.sql

Porównaj listy wtyczek dwóch instalacji (np. staging vs produkcja):

diff <(wp plugin list --format=csv --path=/site1 | awk -F',' '{print $1}' | sort) \ <(wp plugin list --format=csv --path=/site2 | awk -F',' '{print $1}' | sort)

8. Masowe operacje na plikach

Zmiana godzin kontaktu na 40 stronach HTML, zamiana tabulatorów na spacje w całym motywie, konwersja końców linii z Windows na Unix po edycji w Notepadzie, dodanie nagłówka licencji do wszystkich plików PHP – to operacje, które ręcznie zajmują godziny, a z find + sed trwają sekundy. Jeśli wolisz zlecić tego typu prace – w ramach opieki nad WordPress wykonujemy je regularnie.

Masowa zamiana tekstu we wszystkich plikach HTML:

find . -name "*.html" -exec sed -i 's/8:00–21:00/8:00–16:00/g' {} +

Zamiana z obsługą encji HTML (np. &ndash; obok UTF-8 ):

find . -name "*.html" -exec sed -i \ -e 's/8:00–21:00/8:00–16:00/g' \ -e 's/8:00\&ndash;21:00/8:00\&ndash;16:00/g' {} +

Zmień rozszerzenie .jpeg na .jpg:

find wp-content/uploads/ -name "*.jpeg" -exec sh -c 'mv "$1" "${1%.jpeg}.jpg"' _ {} \;

Usuń trailing whitespace z plików PHP:

find wp-content/themes/ -name "*.php" -exec sed -i 's/[[:space:]]*$//' {} +

Zamień tabulatory na 4 spacje:

find wp-content/themes/motyw/ -name "*.php" -exec sed -i 's/\t/ /g' {} +

Znajdź pliki z końcami linii CRLF (Windows):

find wp-content/themes/ -name "*.php" -exec file {} + | grep CRLF

Zamień CRLF na LF:

find wp-content/themes/ -name "*.php" -exec sed -i 's/\r$//' {} +

Dodaj komentarz z datą i autorem na początku plików PHP:

find wp-content/themes/motyw/ -name "*.php" \ -exec sed -i '1i\<?php /* Modified: 2026-03-30 by WebOptimo */' {} +

Zamień adres e-mail we wszystkich plikach HTML:

find . -name "*.html" -exec sed -i 's/kontakt@weboptimo\.pl/contact@weboptimo\.pl/g' {} +

Rekursywna zamiana numeru telefonu:

find . -name "*.html" -exec sed -i 's/+48 600 000 000/+48 608 271 665/g' {} +

Najczęściej zadawane pytania

Flaga -i modyfikuje pliki bezpośrednio (in-place) – bez tworzenia kopii zapasowej. Przed masowymi zmianami na produkcji zawsze wykonaj backup lub użyj sed -i.bak, co zapisze oryginał z rozszerzeniem .bak. Na serwerach testowych i staging sed -i jest w pełni bezpieczne.

Flaga -r przeszukuje pliki rekursywnie i wyświetla dopasowane linie z nazwami plików. Flaga -l (list) sprawia, że grep wypisuje tylko nazwy plików zawierających dopasowanie – bez samych linii. Użyj -rl, gdy interesuje Cię lista plików, a -rn, gdy potrzebujesz numerów linii.

Nie. Baza danych WordPress przechowuje wiele wartości w formacie PHP serialize, który zawiera informację o długości ciągu tekstowego. Zamiana tekstu sedem zmieni treść, ale nie zaktualizuje licznika długości – co uszkodzi dane. Do zamiany w bazie danych WordPress używaj wp search-replace (szczegóły w artykule WP-CLI), który poprawnie obsługuje serializację.

Dodaj --include="*.php" lub --include="*.css" do grep, a -name "*.php" do find. Dzięki temu operacja dotyczy tylko plików o konkretnym rozszerzeniu. Możesz też użyć grep -I (duże i), które automatycznie pomija pliki binarne.

Większość tak, ale macOS używa BSD sed, który wymaga sed -i '' (z pustym argumentem) zamiast sed -i. Grep na macOS nie obsługuje flagi -P (Perl regex) – użyj grep -E lub zainstaluj GNU grep przez Homebrew (brew install grep).

Potrzebujesz pomocy z administracją serwera lub WordPressem?

Jeśli wolisz zlecić audyt bezpieczeństwa, migrację lub optymalizację zamiast robić to samodzielnie – porozmawiajmy. Bez zobowiązań, bez marketingowego żargonu – konkretna propozycja po krótkiej rozmowie.

Telefon

+48 608 271 665

Pn–Pt, 8:00–16:00

E-mail

kontakt@weboptimo.pl

Odpowiadamy w ciągu 24h

Firma

WebOptimo

NIP: 6391758393