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, sed i awk – 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 -1Szukaj 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 0777Masowe 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 fFunkcje shell backdoorów – shell_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 +1MSzukaj $_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_contents i file_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 -rnZamień 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.sqlZamień prefiks tabel w dumpie SQL:
sed -i 's/wp_/wp_klient_/g' dump.sqlZamień 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 -20Waga katalogów uploads per rok:
du -sh wp-content/uploads/20*/ | sort -rhPolicz obrazki PNG/JPG czekające na konwersję do WebP:
find wp-content/uploads/ \( -name "*.png" -o -name "*.jpg" \) | wc -lZnajdź obrazki JPG bez odpowiednika WebP:
find wp-content/uploads/ -name "*.jpg" | while read f; do
[ ! -f "${f%.jpg}.webp" ] && echo "$f"
doneUsuń puste katalogi po czyszczeniu motywu:
find wp-content/themes/stary-motyw/ -type d -empty -deletePolicz linie kodu PHP w motywie (bez pustych i komentarzy):
find wp-content/themes/motyw/ -name "*.php" -exec cat {} + \
| awk 'NF && !/^[[:space:]]*(\/\/|\/\*|\*)/' | wc -lZnajdź pliki CSS/JS niezmieniane od roku – kandydaci na martwy kod:
find wp-content/themes/ \( -name "*.css" -o -name "*.js" \) -mtime +365Znajdź 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 +100kWylistuj wszystkie załadowane fonty w CSS motywu:
grep -rh "@font-face\|woff2\|woff" wp-content/themes/ --include="*.css" | sort -uZnajdź 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"
donePolicz 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 -154. 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 Linux i FreeBSD.
TOP 20 najczęściej odpytywanych URL-i:
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20Adresy IP generujące najwięcej błędów 404:
awk '$9 == 404 {print $1}' access.log | sort | uniq -c | sort -rn | head -10Kto atakuje wp-login.php (próby brute force):
grep "POST /wp-login.php" access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10Ataki 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 -10Rozkład kodów HTTP – 200/301/404/500:
awk '{print $9}' access.log | sort | uniq -c | sort -rnRuch per godzina – wykryj szczyty i anomalie:
awk '{print $4}' access.log | cut -d: -f2 | sort | uniq -cRequesty 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 -cUser agenty skanujące podatności:
grep -i "sqlmap\|nikto\|nmap\|wpscan\|dirbuster" access.log | awk '{print $1}' | sort -uNajwolniejsze zapytania MySQL z slow query log:
awk '/^# Query_time/{time=$3} /^SELECT|^UPDATE/{print time, $0}' slow-query.log \
| sort -rn | head -10Pró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 -rnRequesty zwracające błąd 500 (Internal Server Error):
awk '$9 == 500 {print $4, $7}' access.log | head -205. 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 motywie – query_posts, create_function, mysql_query:
grep -rn "query_posts\|create_function\|mysql_query\|ereg(" wp-content/themes/ --include="*.php"Wszystkie hooki add_action i add_filter w motywie:
grep -rh "add_action\|add_filter" wp-content/themes/motyw/ --include="*.php" | sortWyciągnij same nazwy hooków:
grep -rohP "(add_action|add_filter)\(\s*['\"](\K[^'\"]+)" wp-content/themes/motyw/ | sort -uTemplate 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 -rnCo 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 -rnHardkodowane 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 -rnInline style w szablonach PHP – do przeniesienia do arkusza CSS:
grep -rn 'style="' wp-content/themes/motyw/ --include="*.php" | wc -lZarejestrowane 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.xmlPolicz URL-e w sitemap:
grep -c "<loc>" sitemap.xmlZnajdź pliki .htaccess we wszystkich podkatalogach:
find . -name ".htaccess" -type fUsuń 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"
doneWyciągnij title ze wszystkich plików HTML:
grep -ohP '<title>\K[^<]+' *.htmlPoró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"
doneZnajdź strony bez tagu canonical:
find . -name "*.html" | while read f; do
grep -qL 'rel="canonical"' "$f" && echo "Brak canonical: $f"
done7. 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 -20Policz wpisy per typ posta w eksporcie XML:
grep -oP '<wp:post_type>\K[^<]+' export.xml | sort | uniq -c | sort -rnWyciągnij listę adresów e-mail użytkowników z dumpa:
grep "INSERT INTO.*wp_users" dump.sql | grep -oP "'[^']*@[^']*'" | sort -uPolicz rekordy autoload w wp_options – nadmiar autoload to częsta przyczyna wolnego TTFB:
grep -c "'yes'" dump.sqlPoró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. – obok UTF-8 –):
find . -name "*.html" -exec sed -i \
-e 's/8:00–21:00/8:00–16:00/g' \
-e 's/8:00\–21:00/8:00\–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 CRLFZamień 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 -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).


