Jako WordPress Developer, pewnie spędzasz dużo czasu w kliencie FTP (FileZilla) lub panelu hostingu. To błąd. To, co w FTP zajmuje 15 minut (np. usuwanie folderu cache z 100,000 plików), w terminalu SSH zajmuje 2 sekundy.
W tym poradniku pokażę Ci zestaw komend, bez których senior developerzy nie wyobrażają sobie pracy.
Logowanie SSH kluczem zamiast hasła
Wszystko poniżej zakłada, że jesteś już na serwerze, a sposób logowania decyduje o tym, czy w ogóle będziesz z tego korzystać. Pytanie o hasło przy każdym połączeniu to dokładnie ta doza tarcia, która odsyła człowieka z powrotem do FileZilli. Wygeneruj parę kluczy przez ssh-keygen -t ed25519, wyślij część publiczną komendą ssh-copy-id user@serwer i logowanie skraca się do jednego słowa. Wiele paneli hostingowych ma osobne pole na klucz publiczny i tam pada większość prób: zawartość id_ed25519.pub to jedna linia, a łamanie wiersza wstawione przez edytor wystarczy, żeby serwer przestał ją rozpoznawać. Jeśli logowanie dalej pyta o hasło, połącz się przez ssh -v i przeczytaj linie z publickey, bo tam klient mówi, który klucz zaproponował i co odpowiedział serwer. Sprawdź też port: część dostawców nie używa 22 i wtedy połączenie nie dochodzi nawet do etapu kluczy. Klucz zabezpiecz hasłem, a hasło wpisz raz na sesję do ssh-agent, bo klucz bez frazy to jeden skradziony laptop od dostępu produkcyjnego. Kiedy klucze już działają, poproś hosting o wyłączenie logowania hasłem albo zrób to sam w sshd_config, bo dopóki hasło jest aktywne, boty dalej je zgadują, a Ty tylko przestałeś je widzieć.
Jak zapisać dane logowania serwera w ~/.ssh/config
Wpisywanie za każdym razem ssh -p 2222 -i ~/.ssh/klient_ed25519 [email protected] kończy się tym, że porty i klucze mieszają się między klientami. Klient OpenSSH czyta plik użytkownika ~/.ssh/config, w którym każdy serwer dostaje krótką nazwę (ssh_config(5)):
Host klient-prod
HostName s123.hosting.example
User klient
Port 2222
IdentityFile ~/.ssh/klient_ed25519
IdentitiesOnly yesOd tej chwili ssh klient-prod, scp, sftp i rsync biorą te wartości same. Host obejmuje wszystkie linie pod sobą aż do następnego bloku Host albo Match, HostName to prawdziwy adres serwera, a Port nadpisuje domyślne 22. Większość niespodzianek tłumaczy jedna reguła z dokumentacji: dla każdej opcji wygrywa pierwsza znaleziona wartość, a ssh czyta najpierw parametry z linii poleceń, potem plik użytkownika, na końcu systemowy /etc/ssh/ssh_config. Konkretne hosty stawiaj więc na górze pliku, a ogólny blok Host * na samym dole. Na macOS przewodnik GitHuba po kluczach SSH dopisuje w tym samym bloku AddKeysToAgent yes i UseKeychain yes, żeby hasło do klucza wpisać raz i trzymać je w systemowym pęku kluczy (GitHub Docs).
Jak naprawić błąd too many authentication failures w SSH
Komunikat Too many authentication failures trafia zwykle osoby, które mają klucze do wielu serwerów. Klient po kolei proponuje serwerowi każdy klucz, jaki trzyma ssh-agent, a serwer liczy każdą odrzuconą próbę. Limit ustawia opcja MaxAuthTries po stronie serwera i domyślnie wynosi 6 (sshd_config(5)). Jeśli właściwy klucz stoi w agencie dalej niż na szóstym miejscu, serwer zamknie połączenie, zanim go zobaczy. Rozwiązanie siedzi w bloku z poprzedniej sekcji: IdentitiesOnly yes każe ssh używać wyłącznie skonfigurowanego klucza, nawet jeśli agent oferuje ich więcej (ssh_config(5)). Do jednorazowego testu wystarczy ssh -o IdentitiesOnly=yes -i ~/.ssh/klient_ed25519 [email protected], a ssh -v pokaże w liniach Offering public key, które klucze faktycznie poszły do serwera.
Z tej samej rodziny jest sesja, która zamarza na niestabilnym łączu. ServerAliveInterval 15 w bloku hosta każe klientowi co 15 sekund prosić serwer o odpowiedź przez szyfrowany kanał. Przy domyślnym ServerAliveCountMax równym 3 dokumentacja podaje, że ssh rozłączy się po około 45 sekundach ciszy, zamiast wisieć z zamrożonym terminalem.
1. Jak sprawdzić, co zajmuje miejsce na serwerze
Kiedy hosting krzyczy “Quota Exceeded”, FileZilla nie pomoże. Użyj tego:
du (disk usage)
## Pokaż foldery w bieżącym katalogu, posortowane wg rozmiaru
du -h --max-depth=1 | sort -hrncdu (ncurses disk usage)
Jeśli możesz, wpisz ncdu. To interaktywny menedżer, po którym nawigujesz strzałkami. Na zagraconym serwerze nic tak szybko nie pokazuje, co realnie zajmuje miejsce, zanim zaczniesz czyścić cache i logi. Po du sięgasz, gdy potrzebujesz liczby do wklejenia w zgłoszenie, po ncdu wtedy, gdy jeszcze nie wiesz, czego szukasz. Obie komendy przechodzą całe drzewo katalogów i nie jest to darmowe: na dużym uploads potrafią zająć dysk na minutę, a na współdzielonym hostingu widać to jako wolniejsze ładowanie strony w tym czasie. Jeśli witryna ma ruch, wskaż konkretny podkatalog zamiast katalogu domowego. Żadna z nich nie odpowie Ci, czy miejsce wolno odzyskać, a na typowej instalacji WordPressa podejrzani są zwykle ci sami: paczki zostawione przez wtyczkę backupową w wp-content, stare foldery roczne w uploads i plik error_log odkładany katalog po katalogu.
2. Jak podglądać debug.log WordPressa na żywo
Zamiast ściągać plik debug.log, otwierać go notatnikiem i szukać błędu… oglądaj go na żywo!
tail -f
## ŚLedź ostatnie linie pliku w czasie rzeczywistym
tail -f wp-content/debug.logTeraz odśwież stronę w przeglądarce, a błędy same pojawią się na ekranie. Zakończ skrótem Ctrl+C. Podgląd na żywo ma sens, dopóki potrafisz wywołać błąd na żądanie. Gdy nie potrafisz, interesująca linia dawno przewinęła się w górę, więc zacznij od tail -n 200 wp-content/debug.log i czytaj wstecz. Przy hałaśliwym logu dopisz filtr, tail -f wp-content/debug.log | grep -i fatal zostawia na ekranie tylko to, co wywala stronę, zamiast setek ostrzeżeń o przestarzałych funkcjach. Dwie rzeczy mylą tu najczęściej. Plik powstaje wyłącznie wtedy, gdy w wp-config.php włączone jest WP_DEBUG_LOG, więc pusty terminal zwykle znaczy, że logowanie jest wyłączone, a nie że strona jest zdrowa. I nic tego pliku nie rotuje, więc serwis rzucający notice przy każdym żądaniu urośnie nim do rozmiaru, przez który wrócisz do sekcji o zajętości dysku.
3. Jak znaleźć funkcję w plikach WordPressa przez grep
Szukasz, w którym pliku użyto funkcji add_image_size? Nie ściągaj całego projektu.
grep
## Szukaj frazy "add_image_size" we wszystkich plikach PHP rekurencyjnie
grep -r "add_image_size" .Jeśli chcesz tylko listę plików (bez treści):
grep -rl "add_image_size" .Pełnej wersji używasz, gdy chcesz zobaczyć kod wokół trafienia, wersji z -l, gdy interesuje Cię tylko, która wtyczka odpowiada za dane zachowanie. W motywie to koszt pomijalny, w wp-content/plugins już nie, bo rekurencja wchodzi w każdy katalog vendor, jaki napotka. Dlatego warto dopisać --include='*.php' i --exclude-dir=node_modules. Trafienie zweryfikuj, otwierając plik w tym miejscu, a nie licząc wyniki: ta sama nazwa funkcji pojawia się w kodzie wtyczki, w jej komentarzu dokumentacyjnym i w pliku tłumaczeń, a definicja jest tylko w jednym z tych miejsc.
4. Jak naprawić błąd 403 forbidden przez uprawnienia plików
Często po migracji pliki mają złe uprawnienia. Pamiętaj zasadę:
- Katalogi: 755
- Pliki: 644
find + chmod
Nie rób tego ręcznie. Użyj automatu:
## Ustaw 755 dla wszystkich katalogów
find . -type d -exec chmod 755 {} \;
## Ustaw 644 dla wszystkich plików
find . -type f -exec chmod 644 {} \;Uruchamiaj to, gdy masz objaw: błąd 403 albo nieudany upload. Nie jako profilaktykę. Masowy chmod zrównuje wszystkie świadome wyjątki na instalacji, a najważniejszy z nich to wp-config.php, który trzyma dane dostępowe do bazy i powinien mieć 640 lub mniej, a nie 644, które właśnie mu nadałeś. Pętla dotyka tylko plików należących do Twojego użytkownika, więc na hostingu, gdzie serwer WWW działa na innym koncie, potrafi nie naprawić niczego i nie zgłosić przy tym błędu. Sprawdzaj efekt przez ls -l wp-config.php i przez wejście na stronę, która nie działała, nigdy przez powtórzenie tej samej komendy.
5. Jak zrobić backup WordPressa przez SSH poleceniem tar
Chcesz zrobić szybki backup przed aktualizacją? Nie kopiuj przez FTP (trwa wieki). Spakuj na serwerze.
tar
## Stwórz archiwum backup.tar.gz z całego katalogu
tar -czf backup.tar.gz .Rozpakowanie:
tar -xzf backup.tar.gzPakowanie na serwerze jest właściwym ruchem przed aktualizacją wtyczki, bo archiwum nie przechodzi przez Twoje łącze. Nie jest za to strategią backupu: paczka leży na tym samym dysku co strona, więc przetrwa nieudaną aktualizację, ale nie awarię wolumenu. Dopisz --exclude='wp-content/cache', chyba że chcesz zarchiwizować dokładnie to, co za chwilę skasujesz. Zanim uwierzysz archiwum, zajrzyj do niego przez tar -tzf backup.tar.gz | head, bo paczka ucięta przez pełny dysk w listingu katalogu wygląda jak każdy inny plik.
6. Jak wyeksportować i zaimportować bazę WordPress przez WP-CLI
Jeśli masz WP-CLI (a powinieneś), nie musisz logować się do phpMyAdmin.
## Eksport bazy (backup)
wp db export backup.sql
## Import bazy
wp db import backup.sql
## Wyczyść bazę (uwaga!)
wp db resetWP-CLI wygrywa w chwili, w której baza jest na tyle duża, że przeglądarka odpuszcza w połowie eksportu. Działa jako Twój użytkownik powłoki, a nie przez serwer WWW, więc limity uploadu i czasu wykonania PHP przestają obowiązywać. Czego nie pominie, to fakt, że strona żyje: wp db import kasuje i odtwarza tabele w trakcie, gdy ktoś czyta stronę, więc okno serwisowe jest częścią tej komendy, a nie dodatkiem. Wynik sprawdzisz jednym wp option get siteurl, które zgłosi błąd natychmiast, jeśli import wszedł tylko w połowie.
7. Jak szybko usunąć folder cache przez SSH
Usuwanie folderu cache wtyczki, który ma milion małych plików, przez FTP może zająć godzinę (FTP kasuje plik po pliku).
rm
## Usuń folder i wszystko w środku (bez powrotu!)
rm -rf wp-content/cache/Czas trwania: 0.5 sekundy. To właściwe narzędzie do katalogu z cache i prawie nigdy właściwe do czegokolwiek innego, bo nie ma tu pytania o potwierdzenie ani drogi powrotnej. Nawyk, który ratuje, jest jeden: najpierw ls na dokładnie tej samej ścieżce, kasowanie dopiero wtedy, gdy listing zgadza się z tym, co masz w głowie. Szczególnie pilnuj końcówki ścieżki, bo przypadkowa spacja robi z jednego celu dwa, a tym drugim bywa katalog nadrzędny. Na ruchliwym serwisie wtyczka odbuduje cache przy najbliższym żądaniu, więc płacisz jednym wolniejszym wczytaniem strony, a nie niedostępnością.
8. Jak synchronizować pliki WordPressa przez rsync
FTP za każdym razem wysyła wszystko od nowa. rsync najpierw porównuje obie strony i przesyła wyłącznie różnicę, więc synchronizacja katalogu uploads przestaje być pretekstem na kawę.
rsync
## Najpierw na sucho: pokaż co zostałoby skopiowane, nie zmieniaj niczego
rsync -avzn --exclude 'cache/' ./wp-content/uploads/ user@serwer:/var/www/przyklad.pl/wp-content/uploads/Kiedy lista plików wygląda sensownie, usuń n z -avzn. Dwa nawyki warto mieć na stałe. Ukośnik na końcu ścieżki źródłowej znaczy “zawartość tego katalogu”; bez niego wyląduje Ci uploads/uploads. A --delete odwzorowuje też kasowanie, czyli usuwa z serwera to, czego nie ma lokalnie. Odpalone z nieaktualnej kopii na żywym sklepie nie synchronizuje biblioteki mediów, tylko ją czyści.
Na części polskich hostingów współdzielonych rsync nie jest zainstalowany po stronie serwera, a bez niego komenda nie zadziała, bo potrzebuje binarki po obu stronach. Sprawdź to jednym ssh user@serwer 'which rsync' zanim zaplanujesz na tym wdrożenie.
9. Jak połączyć się z MySQL na serwerze przez tunel SSH
Hostingi zarządzane zwykle zamykają MySQL na świat. Port 3306 odpowiada tylko z localhosta, więc klient na desktopie się nie połączy, a w panelu zostaje phpMyAdmin. Nie potrzebujesz otwartego portu, potrzebujesz tunelu.
ssh -L
## Przepnij lokalny port 3307 na MySQL serwera, bez otwierania zdalnej powłoki
ssh -N -L 3307:127.0.0.1:3306 user@serwerZostaw ten terminal otwarty i ustaw w TablePlus, DBeaverze albo w zwykłym kliencie mysql adres 127.0.0.1:3307. -N znaczy “żadnej zdalnej komendy”, sesja tylko przekazuje ruch. Tym samym sposobem dosięgniesz wszystkiego, co nasłuchuje na localhoście: Redisa na 6379, aplikacji stagingowej na 8080, endpointu, który nigdy nie miał być publiczny. Wybierz lokalny port, który faktycznie jest wolny, bo ssh zgłosi nieudany bind i mimo to utrzyma sesję, co wygląda na działający tunel aż do pierwszego zapytania, które zawiśnie.
10. Jak zmienić domenę WordPress przez WP-CLI search-replace
Po migracji w bazie siedzi stara domena, a spora jej część leży w serializowanych tablicach PHP, gdzie każdy string ma zapisaną własną długość. Zwykłe UPDATE ... REPLACE podmieni tekst i zostawi błędną długość, więc widgety, opcje motywu i układy z page buildera wrócą puste. WP-CLI rozumie serializację i zanim cokolwiek ruszy, pokaże Ci co zamierza ruszyć.
wp search-replace --dry-run
## Policz co by się zmieniło, nie zapisuj nic
wp search-replace 'https://staging.przyklad.pl' 'https://przyklad.pl' --dry-run --all-tables-with-prefix --report-changed-onlyDostajesz tabelę z liczbą trafień w każdej kolumnie. Kiedy liczby zgadzają się z tym, czego się spodziewasz, powtórz komendę bez --dry-run. Dodaj --precise, jeśli strona ma zagnieżdżoną serializację, bo wymusza wolniejszą ścieżkę po stronie PHP zamiast skrótu po SQL, a --recurse-objects, gdy w grę wchodzą serializowane obiekty. Tak czy inaczej zrób najpierw wp db export: search-replace nie ma cofnięcia.
Jak monitorować CPU, pamięć i procesy na serwerze
Zużycie zasobów na żywo
# Pokaż procesy, które zużywają najwięcej zasobów na serwerze WordPressa
top
# Wersja ulepszona (jeśli jest dostępna)
htop
# Pokaż zużycie pamięci
free -h
# Pokaż zajętość dysku według partycji
df -h
# Pokaż aktywne połączenia sieciowe
netstat -tulnJak znaleźć ciężkie procesy PHP
# Pokaż aktywne procesy PHP
ps aux | grep php
# Pokaż zapytania, które MySQL wykonuje w tej chwili
mysqladmin -u root -p processlistTe komendy odpowiadają na inne pytanie niż te od dysku: nie co zajmuje miejsce, tylko co w tej chwili zużywa procesor. Gdy na górze listy wisi kilka procesów PHP, winowajcą prawie nigdy nie jest sam WordPress, tylko wolne zapytanie albo cron, który nakłada się sam na siebie, bo poprzednie uruchomienie jeszcze się nie skończyło. Sprawdź tę hipotezę przez wp cron event list, zanim ruszysz serwer. I pamiętaj, że na hostingu współdzielonym widzisz procesy całej maszyny, więc wysokie obciążenie może nie mieć nic wspólnego z twoją stroną.
Jak tworzyć aliasy i skrypty konserwacyjne dla WordPressa
Utwórz aliasy dla komend, których często używasz:
# Dodaj do ~/.bashrc lub ~/.zshrc
alias wplog='tail -f wp-content/debug.log'
alias wpsize='du -h --max-depth=1 | sort -hr'
alias wpcache='rm -rf wp-content/cache/*'
alias wpdb='wp db export backup-$(date +%Y%m%d).sql'
alias wpcheck='wp core verify-checksums && wp plugin list --update=available'Automatyczny skrypt konserwacyjny
#!/bin/bash
# Codzienny skrypt konserwacji WordPressa
echo "=== Konserwacja WordPressa $(date) ==="
# Kopia bazy danych
wp db export /kopie/db-$(date +%Y%m%d).sql
echo "Kopia bazy zrobiona"
# Weryfikacja integralności rdzenia
wp core verify-checksums
echo "Rdzeń zweryfikowany"
# Lista dostępnych aktualizacji
echo "=== Dostępne aktualizacje ==="
wp plugin list --update=available
wp theme list --update=available
wp core check-update
# Usunięcie wygasłych transientów
wp transient delete --expired
echo "Transienty wyczyszczone"
# Optymalizacja bazy danych
wp db optimize
echo "Baza zoptymalizowana"
echo "=== Konserwacja zakończona ==="Jak uruchomić WP-CLI na zdalnym serwerze z własnego komputera
WP-CLI potrafi wykonać komendę na innej maszynie przez SSH, więc nie musisz najpierw otwierać powłoki. Podręcznik WP-CLI opisuje globalny parametr --ssh w postaci [<scheme>:][<user>@]<host>[:<port>][<path>] (Running commands remotely):
wp [email protected]:2222/home/klient/public_html plugin listŚcieżka idzie zaraz po porcie. Jeśli podasz sam host, użytkownikiem będzie Twój lokalny login, portem 22, a ścieżką katalog domowy użytkownika SSH. Działa też alias z ~/.ssh/config, więc wp --ssh=klient-prod przejmie port i klucz z sekcji o tym pliku. Dla projektów, do których wracasz często, zapisz aliasy w wp-cli.yml projektu albo w globalnym ~/.wp-cli/config.yml:
@prod:
ssh: [email protected]/home/klient/public_html
@staging:
ssh: [email protected]/home/klient/staging
@both:
- @prod
- @stagingWtedy wp @prod core version pyta produkcję, a grupa @both wykonuje wp @both core check-update na obu instalacjach naraz. Warunek, o który potyka się większość hostingów współdzielonych: WP-CLI musi być zainstalowane na serwerze i dostępne jako wp w jego $PATH. Sesja SSH uruchomiona w ten sposób nie wczytuje ~/.bashrc, więc wp ustawione tam jako alias nie zostanie znalezione. Podręcznik radzi położyć plik wykonywalny w $HOME/bin/wp. Przez Twoje łącze idzie tylko komenda i jej wynik, dlatego tak wygodnie puszcza się wp search-replace --dry-run z poprzedniej sekcji na żywej stronie.
Co zrobić, gdy hosting ma tylko SFTP
Część pakietów współdzielonych reklamuje SSH, a dostarcza SFTP, czyli transfer plików tym samym protokołem, tylko bez powłoki po drugiej stronie. Dowiadujesz się o tym w momencie, gdy ssh user@host 'ls' odpowiada exec request failed on channel 0. Nic z tego poradnika, co wykonuje się na serwerze, tam nie zadziała: ani du, ani tar, ani WP-CLI, bo nie ma procesu, który mógłby je uruchomić. Warstwa transferu nadal działa, więc sftp przenosi pliki szybciej i pewniej niż klient z oknem (rsync już nie, bo musi uruchomić swój proces po drugiej stronie), a robota przy bazie wraca do przeglądarki, do phpMyAdmina i wtyczki backupowej. Zanim się z tym pogodzisz, sprawdź, czy dostawca nie wystawia powłoki na innym porcie albo nie włącza jej na zgłoszenie, bo u kilku polskich hostingów to ustawienie w panelu, a nie granica usługi. Jeśli faktycznie tego nie ma, masz twardy argument za migracją, bo cały ten artykuł jest w tym pakiecie zamknięty.
Podsumowanie
Terminal SSH nie gryzie. Pozwala Ci pracować z prędkością dysku serwera, a nie prędkością Twojego łącza internetowego. Zacznij od ncdu i tail -f, zobaczysz, że nie będziesz chciał wracać do klikania myszką.






