From aa494fd8e24b0aabcc890655370a15358f9e6755 Mon Sep 17 00:00:00 2001 From: ertopogo Date: Thu, 5 Feb 2026 23:48:50 +0100 Subject: WIP: prepare import csv --- DOC_TECHNIQUE.md | 569 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 532 insertions(+), 37 deletions(-) (limited to 'DOC_TECHNIQUE.md') diff --git a/DOC_TECHNIQUE.md b/DOC_TECHNIQUE.md index ffd108c..0c4b2f9 100644 --- a/DOC_TECHNIQUE.md +++ b/DOC_TECHNIQUE.md @@ -4,7 +4,7 @@ Ce document explique l'architecture, les technologies, la mise en place, les tes et la sauvegarde/restauration du magasin en ligne. Il est ecrit pour une personne junior afin de pouvoir prendre en main le projet en autonomie. -## 1) Vue d'ensemble +## 1. Vue d'ensemble Le projet est compose de : - **Backend MedusaJS** : API ecommerce (produits, panier, commandes). @@ -19,7 +19,7 @@ Ports principaux : - `9000` : backend (API + admin) - `6379` : redis -## 1.1) Redis (pourquoi et comment) +### 1.1 Redis (pourquoi et comment) Redis est une base cle-valeur en memoire, utilisee pour : - **cache** : accelerer certaines lectures. @@ -39,17 +39,17 @@ Ou le voir : - `backend/medusa-config.js` -> `eventBus` et `cacheService`. - `docker-compose.yml` -> service `redis`. -## 2) Technologies utilisees (liens utiles) +## 2. Technologies utilisees (liens utiles) -- MedusaJS : https://docs.medusajs.com/ -- Next.js : https://nextjs.org/docs -- Docker : https://docs.docker.com/get-started/ -- Docker Compose : https://docs.docker.com/compose/ -- PostgreSQL : https://www.postgresql.org/docs/ -- Redis : https://redis.io/docs/latest/ -- Apache reverse proxy : https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html +- [MedusaJS](https://docs.medusajs.com/) +- [Next.js](https://nextjs.org/docs) +- [Docker](https://docs.docker.com/get-started/) +- [Docker Compose](https://docs.docker.com/compose/) +- [PostgreSQL](https://www.postgresql.org/docs/) +- [Redis](https://redis.io/docs/latest/) +- [Apache reverse proxy](https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html) -## 3) Fichiers importants +## 3. Fichiers importants - `docker-compose.yml` : configuration des conteneurs. - `backend/` : code et config Medusa. @@ -57,7 +57,7 @@ Ou le voir : - `.env` : variables d'environnement (non versionne). - `env-example` : modele de variables d'environnement. -## 3.1) D'ou vient le code (YAML vs depot) +### 3.1 D'ou vient le code (YAML vs depot) Le fichier `docker-compose.yml` **ne contient pas le code** : - il **decrit** comment lancer les conteneurs (services, ports, variables). @@ -68,7 +68,7 @@ Flux reel : 2) `docker compose build` construit les images depuis les Dockerfile. 3) `docker compose up` lance les conteneurs avec les variables `.env`. -## 3.2) Medusa (backend) - installation technique +### 3.2 Medusa (backend) - installation technique Etapes principales : 1) `backend/Dockerfile` copie `package.json`, installe les deps. @@ -88,13 +88,13 @@ Briques logicielles principales : - **Redis** : cache + event bus. - **MedusaJS** : API ecommerce (services, modules, plugins). -## 3.3) Storefront (frontend) - fonctionnement +### 3.3 Storefront (frontend) - fonctionnement - Next.js compile le site au build (`npm run build`). - La variable `NEXT_PUBLIC_MEDUSA_BACKEND_URL` est **injectee au build**. - Le conteneur expose le site sur le port `8000`. -## 3.4) Schema technique (ASCII) +### 3.4 Schema technique (ASCII) ``` +----------------------+ @@ -119,7 +119,7 @@ Briques logicielles principales : +---------------+ +----------------+ ``` -## 4) Installation rapide (serveur) +## 4. Installation rapide (serveur Linux) 1. Copier la configuration : ``` @@ -141,7 +141,7 @@ COOKIE_SECRET=change_me docker compose up -d --build ``` -### 4.1) Exemple reel (ce que nous avons fait) +### 4.1 Exemple reel (ce que nous avons fait) Contexte : backend sur `192.168.99.22:9000`, storefront sur `192.168.99.22:8000`. @@ -174,7 +174,13 @@ curl -v http://192.168.99.22:8000 sudo docker compose run --rm backend npm run seed ``` -## 5) Tests rapides +5) Import CSV produits : +``` +sudo docker compose run --rm backend npm run import:products +``` +Doc: `DOC_IMPORT_PRODUITS.md` + +## 5. Tests rapides (serveur Linux) Verifier que les conteneurs tournent : ``` @@ -197,7 +203,7 @@ docker compose logs -f backend docker compose logs -f storefront ``` -### 5.1) Logs systeme avec journalctl (systemd) +### 5.1 Logs systeme avec journalctl (systemd) Utiliser `journalctl` pour diagnostiquer les services systeme (Apache, dnsmasq, Docker). @@ -242,7 +248,7 @@ sudo journalctl -n 50 --no-pager sudo journalctl -u dnsmasq -S "10 min ago" --no-pager ``` -### 5.2) Tests CORS (exemple utilise) +### 5.2 Tests CORS (exemple utilise) ``` curl -i -H "Origin: http://192.168.99.22:8000" http://192.168.99.22:9000/store/products @@ -250,7 +256,7 @@ curl -i -H "Origin: http://192.168.99.22:8000" http://192.168.99.22:9000/store/p - Confirme que `Access-Control-Allow-Origin` autorise le storefront. -## 6) Ou se trouve la base de donnees ? +## 6. Ou se trouve la base de donnees ? Le backend lit la base de donnees via `DATABASE_URL` dans `.env`. Le format est : @@ -261,9 +267,9 @@ postgres://user:password@host:5432/nom_db Si PostgreSQL est externe au serveur, verifier l'ouverture du port `5432` et les autorisations reseau (pg_hba.conf cote PostgreSQL). -## 7) Debogage courant +## 7. Debogage courant (serveur Linux) -### Backend qui redemarre en boucle +### 7.1 Backend qui redemarre en boucle Ca arrive si : - `DATABASE_URL` est incorrect - les migrations ne sont pas faites @@ -275,7 +281,7 @@ docker compose logs -f backend docker exec -it medusa-backend npm run seed ``` -### Storefront affiche "Chargement des produits..." +### 7.2 Storefront affiche "Chargement des produits..." Le storefront attend l'API backend. Verifier : - `NEXT_PUBLIC_MEDUSA_BACKEND_URL` dans `.env` - le backend repond sur `:9000` @@ -288,7 +294,7 @@ sudo docker compose up -d --build storefront - verifier que `storefront/pages/_app.js` utilise `process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL` (pas `localhost` en dur). -### Admin Medusa (login qui boucle) +### 7.3 Admin Medusa (login qui boucle) Symptome : l'admin reste sur la page de login. Cause frequente : cookies `Secure` bloques en HTTP si `NODE_ENV=production`. @@ -301,7 +307,7 @@ Solution appliquee : sudo docker compose up -d --build backend ``` -### CORS admin/storefront (procedure) +### 7.4 CORS admin/storefront (procedure) Objectif : autoriser le navigateur a appeler l'API depuis le storefront et l'admin. @@ -321,7 +327,7 @@ sudo docker compose up -d --build backend curl -i -H "Origin: http://:8000" http://:9000/store/products ``` -### Admin en HTTP (procedure NODE_ENV) +### 7.5 Admin en HTTP (procedure NODE_ENV) Objectif : eviter le blocage des cookies `Secure` en HTTP. @@ -340,7 +346,7 @@ NODE_ENV=development sudo docker compose up -d --build backend ``` -### Patch Medusa (TypeORM update vide) +### 7.6 Patch Medusa (TypeORM update vide) Probleme : - Erreur TypeORM `Empty criteria(s) are not allowed for the update method`. @@ -367,13 +373,13 @@ sudo docker compose build --no-cache backend sudo docker compose up -d backend ``` -## 8) Mise en production (reverse proxy) +## 8. Mise en production (reverse proxy, serveur Linux) Pour exposer en HTTP/HTTPS, utiliser Apache ou Nginx. Exemple Apache : - `apache-vhost.conf` dans le repo - activer `proxy` et `proxy_http` -## 9) Sauvegarde et restauration +## 9. Sauvegarde et restauration (serveur Linux) Objectif : pouvoir recuperer **tout le site** et **l'historique**. Il faut sauvegarder : @@ -387,7 +393,7 @@ Sur le serveur de DB : ``` pg_dump -Fc -U user nom_db > /backups/lucien-sens-bon.dump ``` -Doc officielle : https://www.postgresql.org/docs/current/app-pgdump.html +Doc officielle : ### 9.2 Sauvegarde des uploads Si le backend stocke des fichiers : @@ -413,7 +419,7 @@ tar -czf /backups/lucien-sens-bon-config.tgz \ ``` pg_restore -U user -d nom_db /backups/lucien-sens-bon.dump ``` -Doc : https://www.postgresql.org/docs/current/app-pgrestore.html +Doc : 2) Restaurer les fichiers : ``` @@ -426,14 +432,14 @@ tar -xzf /backups/lucien-sens-bon-config.tgz -C / docker compose up -d --build ``` -## 10) Bonnes pratiques +## 10. Bonnes pratiques - Toujours versionner le code via Git (ne pas modifier uniquement sur serveur). - Sauvegarder la DB quotidiennement. - Garder un backup hors serveur (S3, autre machine). - Tester les restaurations une fois par trimestre. -## 11) Procedure Git (push + alignement serveur) +## 11. Procedure Git (push + alignement serveur) Objectif : pousser le code vers `chillka`, puis aligner `huitral` **sans perdre de changements**. @@ -545,9 +551,9 @@ Representation locale d'une branche distante : - Quand on fait `git fetch`, Git met a jour `refs/remotes/origin/main`. - Quand on fait `git merge origin/main`, on integre cette reference distante dans la branche locale `main`. -### 11.5 Recuperer sur antel et nettoyer les fichiers .txt +### 11.5 Recuperer sur antel et nettoyer les fichiers .txt (poste Windows/WSL) -#### a) Recuperer les mises a jour depuis chillka +#### 11.5.1 Recuperer les mises a jour depuis chillka Sur antel : ``` cd /mnt/e/Dev/Web-Works/Lucien-sens-bon @@ -571,7 +577,7 @@ Explication rapide : - `git commit` : sauvegarder les changements locaux. - `git pull --rebase` : rejouer ces commits au-dessus de `origin/main` pour eviter un merge commit. -#### b) Retirer des fichiers .txt deja stages +#### 11.5.2 Retirer des fichiers .txt deja stages Si des fichiers .txt ne doivent pas etre versionnes : ``` git restore --staged _fichier-avec-erreurs/*.txt @@ -581,3 +587,492 @@ Explication rapide : - `git restore --staged` : retire les fichiers de l'index sans toucher le disque. - `rm -f` : supprime les fichiers localement. +## 12. Commandes et diagnostics (annexe) + +Cette annexe regroupe les commandes utilisees dans le projet, par theme, avec +les objectifs, parametres importants et alternatives utiles. +Les commandes sont separees entre **serveur Linux** et **poste Windows/WSL**. + +### 12.1 Serveur Linux + +#### 12.1.1 Docker / Docker Compose (services Medusa + Storefront + Redis) + +**Lancer les services** +``` +docker compose up -d --build +``` +- `docker compose` : plugin Compose integre (recommande). +- `up` : cree et demarre les services. +- `-d` : detache (retourne la main). +- `--build` : reconstruit les images si necessaire. +Alternatives : +- `docker-compose up -d --build` (ancienne syntaxe). +- `docker compose up` (sans `-d` : logs en direct). + +**Voir l'etat des conteneurs** +``` +docker compose ps +``` +- aucun : liste services, statuts, ports. +Alternatives : +- `docker ps` (tous les conteneurs). +- `docker compose ps -a` (inclut les arretes). + +**Voir les logs** +``` +docker compose logs -f +docker compose logs -f backend +docker compose logs -f storefront +``` +- `-f` : suivi temps reel (equivalent `tail -f`). +- `backend` / `storefront` : filtre par service. +Alternatives : +- `docker logs -f ` +- `docker compose logs --tail=200 backend` + +**Redemarrer un service** +``` +docker compose restart backend +``` +- redemarre le service sans reconstruire l'image. +Alternatives : +- `docker compose up -d backend` +- `docker compose up -d --build backend` + +**Rebuild force d'un service** +``` +docker compose build --no-cache backend +docker compose up -d --build backend +``` +- `--no-cache` : force l'installation des deps + postinstall. +- `--build` : rebuild puis redeploiement. +Alternatives : +- `docker compose build backend` (cache autorise). + +**Entrer dans un conteneur** +``` +docker exec -it medusa-backend sh +``` +- `exec` : execute une commande dans un conteneur. +- `-it` : mode interactif + TTY. +- `sh` : shell minimal. +Alternatives : +- `docker exec -it medusa-backend bash` (si `bash` present). +- `docker compose exec backend sh` + +**Commande dans un conteneur temporaire** +``` +docker compose run --rm backend +``` +- `run` : conteneur ponctuel base sur le service. +- `--rm` : supprime le conteneur a la fin. +Alternatives : +- `docker run --rm -it ` + +#### 12.1.2 PostgreSQL (connexion, diagnostic, sauvegarde) + +**Connexion via `DATABASE_URL`** +``` +psql "$DATABASE_URL" -c "select 1;" +``` +- `$DATABASE_URL` : `postgres://user:pass@host:5432/db` +- `-c` : execute une requete et quitte. +Alternatives : +- `psql -h -U -d -W` +- `docker run --rm -it postgres:16-alpine psql "$DATABASE_URL" -c "select 1;"` + +**Test du port reseau PostgreSQL** +``` +nc -vz 5432 +``` +- `-v` : verbose. +- `-z` : scan sans envoyer de donnees. +Alternatives : +- `telnet 5432` +- `bash -c ">/dev/tcp//5432"` (si bash) + +**Diagnostic hote (service / process)** +``` +sudo systemctl status postgresql +sudo service postgresql status +ps aux | grep -E "postgres|postmaster" +``` +- `systemctl` / `service` : verifie service systemd/sysv. +- `ps + grep` : liste les processus. +Alternatives : +- `pgrep -a postgres` +- `ss -lntp | grep 5432` + +**Localiser la configuration** +``` +sudo -u postgres psql -c "SHOW config_file;" +sudo -u postgres psql -c "SHOW hba_file;" +sudo -u postgres psql -c "SHOW data_directory;" +``` +- donne les chemins exacts des fichiers de config et des donnees. +Alternatives (chemins typiques) : +- `/etc/postgresql/*/main/postgresql.conf` +- `/etc/postgresql/*/main/pg_hba.conf` +- `/var/lib/pgsql/data/postgresql.conf` +- `/var/lib/pgsql/data/pg_hba.conf` + +**Commandes `psql` utiles (dans psql)** +``` +\du +\l +\c ma_base +\dt +SHOW port; +SHOW listen_addresses; +``` +- `\` : commandes internes psql. +- `SHOW ...` : variables de configuration. +Alternatives : +- `SELECT current_user;` +- `SELECT version();` + +**Sauvegarde et restauration** +``` +pg_dump -Fc -U user nom_db > /backups/lucien-sens-bon.dump +pg_restore -U user -d nom_db /backups/lucien-sens-bon.dump +``` +- `-Fc` : format custom (compresse + restauration selective). +- `-U` : utilisateur. +Alternatives : +- `pg_dump -U user nom_db > dump.sql` +- `psql -U user -d nom_db < dump.sql` + +#### 12.1.3 Medusa / Node.js (backend) + +**Migrations Medusa** +``` +docker compose run --rm backend npx medusa migrations run +``` +- applique les migrations (creation des tables). +- `npx` : execute la version locale de Medusa. +Alternatives : +- `docker exec -it medusa-backend npx medusa migrations run` + +**Seed de donnees** +``` +docker compose run --rm backend npm run seed +``` +- injecte des donnees demo si `backend/data/seed.json` existe. +Alternatives : +- `docker exec -it medusa-backend npm run seed` + +**Import CSV produits** +``` +docker compose run --rm backend npm run import:products +``` +- importe les produits depuis `backend/data/products-import.csv` via `external_id`. +- doc: `DOC_IMPORT_PRODUITS.md` +Alternatives : +- `docker exec -it medusa-backend npm run import:products` + +**Creation utilisateur admin (Medusa)** +``` +docker exec -it medusa-backend medusa user -e admin@lucien.com -p supersecret +``` +- `-e` : email de l'admin. +- `-p` : mot de passe. +Alternatives : +- `medusa user --help` + +**Test DB via Node (diagnostic)** +``` +docker compose run --rm backend node -e "const { Client }=require('pg'); ... " +``` +- `node -e` : execute un script JS en ligne. +- `pg` : client PostgreSQL Node. +Alternatives : +- script JS temporaire dans le conteneur. +- `psql` direct (plus simple si acces). + +#### 12.1.4 Storefront / Tests HTTP (curl) + +**Test de l'API Medusa** +``` +curl http://localhost:9000/store/products +``` +- URL endpoint public Medusa. +Alternatives : +- `curl -v ...` +- `http :9000/store/products` (httpie) + +**Test du storefront** +``` +curl http://localhost:8000 +``` +- verifie que le site repond. +Alternatives : +- `curl -I http://localhost:8000` + +**Test CORS** +``` +curl -i -H "Origin: http://:8000" http://:9000/store/products +``` +- `-i` : inclut les en-tetes. +- `-H` : ajoute un header `Origin`. +Alternatives : +- `curl -v ...` +- DevTools navigateur (onglet Network). + +#### 12.1.5 Apache / Reverse proxy + +**Statut Apache** +``` +sudo systemctl status apache2 +``` +Alternatives : +- `sudo service apache2 status` + +**Logs Apache** +``` +sudo journalctl -u apache2 -f +sudo tail -f /var/log/apache2/error.log +sudo tail -f /var/log/apache2/access.log +``` +- `-f` : suivi temps reel. +Alternatives : +- `journalctl -u apache2 -n 200 --no-pager` + +**Modules proxy** +``` +sudo a2enmod proxy +sudo a2enmod proxy_http +``` +- active les modules de reverse proxy. +Alternatives : +- `a2enmod headers` +- `a2enmod rewrite` + +**Reload Apache** +``` +sudo systemctl reload apache2 +``` +- recharge la config sans couper les connexions actives. +Alternatives : +- `sudo service apache2 restart` + +**Activer un vhost** +``` +sudo a2ensite lucien.conf +sudo apache2ctl configtest +sudo service apache2 restart +``` +- `configtest` : verifie la syntaxe avant redemarrage. + +#### 12.1.6 Systemd / Logs systeme (journalctl) + +**Base** +``` +sudo journalctl --disk-usage +sudo journalctl --list-boots +sudo journalctl -u -n 50 --no-pager +sudo journalctl -u -f +``` +- `-u` : filtre par service. +- `-n` : n dernieres lignes. +- `-f` : suivi temps reel. +- `-b` : dernier boot. +- `-S` : depuis une date (ex: `10 min ago`). +- `--no-pager` : pas de pagination. + +#### 12.1.7 Reseau / Ports (diagnostic) + +**Ports locaux** +``` +ss -lntp | egrep '8000|9000|5432|6379' +netstat -lntp | egrep '8000|9000|5432|6379' +``` +- `ss` : outil moderne (remplace netstat). +- `-l` listening, `-n` numerique, `-t` TCP, `-p` process. +Alternatives : +- `lsof -iTCP -sTCP:LISTEN -n -P` + +**Firewall** +``` +sudo ufw status +``` +Alternatives : +- `sudo iptables -S` +- `sudo firewall-cmd --list-all` + +#### 12.1.8 Fichiers / Permissions + +**Verifier presence d'un fichier** +``` +ls -l docker-compose.yml +ls -l /etc/resolv.conf +``` +- `-l` : details (droits, owner). +Alternatives : +- `stat ` + +**Corriger les permissions du depot** +``` +sudo chown -R "$USER":"$USER" /var/www/lucien-sens-bon +``` +- redonne les droits a l'utilisateur courant. +Alternatives : +- `sudo chgrp -R ` +- `sudo chmod -R g+w ` + +#### 12.1.9 Git (workflow et maintenance) + +**Etat et staging** +``` +git status +git add -A +git reset HEAD .env output*.txt +``` +- `add -A` : indexe ajouts + modifs + suppressions. +- `reset HEAD ...` : retire du staging sans toucher le disque. +Alternatives : +- `git add ` +- `git restore --staged ` + +**Commit avec identite temporaire** +``` +GIT_AUTHOR_NAME="toshiro" GIT_AUTHOR_EMAIL="toshiro@chillka" \ +GIT_COMMITTER_NAME="toshiro" GIT_COMMITTER_EMAIL="toshiro@chillka" \ +git commit -m "local changes on huitral" +``` +- fixe l'identite uniquement pour cette commande. +Alternatives : +- `git -c user.name="..." -c user.email="..." commit -m "..."` + +**Suivi de branche distante** +``` +git branch --set-upstream-to=origin/docs-git-dns +``` +- associe la branche locale a la branche distante. +Alternatives : +- `git push -u origin ` + +**Mise a jour sans merge commit** +``` +git pull --rebase +git fetch origin +git pull --rebase origin docs-git-dns +``` +- `rebase` : rejoue les commits locaux au-dessus de la remote. +Alternatives : +- `git pull --ff-only` + +**Aligner strictement sur la remote (ATTENTION)** +``` +git fetch origin +git reset --hard origin/main +git clean -fd +``` +- ecrase les changements locaux + supprime les fichiers non suivis. +Alternatives : +- `git stash push -u -m "wip"` + +**Stash pour rebase** +``` +git stash push -u -m "wip avant rebase" +git stash pop +``` +- sauvegarde temporaire des modifs non committes. +Alternatives : +- `git add -A` + `git commit` (si vous preferez un commit). + +**References Git** +``` +git branch -a +git show-ref --heads +git show-ref --tags +``` +- affiche les branches locales, distantes et tags. + +#### 12.1.10 Sauvegardes fichiers et depot + +**Sauvegarder les uploads** +``` +tar -czf /backups/medusa-uploads.tgz /var/www/lucien-sens-bon/backend/uploads +``` +- `-c` : create, `-z` : gzip, `-f` : fichier output. +Alternatives : +- `rsync -a` (sauvegarde incrementale). + +**Sauvegarder la config projet** +``` +tar -czf /backups/lucien-sens-bon-config.tgz \ + /var/www/lucien-sens-bon/.env \ + /var/www/lucien-sens-bon/docker-compose.yml +``` +- archive les fichiers critiques de config. + +**Sauvegarder le depot Git (bare)** +``` +git clone --mirror toshiro@chillka:/var/data/git/repositories/lucien-sens-bon.git \ + /backups/lucien-sens-bon.git +``` +- `--mirror` : sauvegarde complete des refs/branches/tags. +Alternatives : +- `git bundle create backup.bundle --all` + +#### 12.1.11 Edition / fichiers d'environnement + +**Copier le modele `.env`** +``` +cp env-example .env +``` +- cree un fichier `.env` local avec les variables par defaut. +Alternatives : +- `cp -n env-example .env` (n'ecrase pas si `.env` existe). + +**Editer un fichier** +``` +vim .env +``` +Alternatives : +- `nano .env` +- `code .env` + +#### 12.1.12 Outils divers utiles + +**Tests HTTP rapides (headers only)** +``` +curl -I http://localhost:9000/store/products +``` +- `-I` : en-tetes uniquement (plus rapide). +Alternatives : +- `wget --spider ` + +**Recherche dans un conteneur** +``` +docker compose run --rm backend sh -c "rg -n \"update\\(\\{\\},\" node_modules/@medusajs/medusa/dist/services" +``` +- `rg -n` : recherche rapide avec numeros de lignes. +Alternatives : +- `grep -n ` + +### 12.2 Poste Windows (et WSL) + +#### 12.2.1 DNS / Resolution (Windows + WSL) + +**DNS local (Windows)** +``` +nslookup www.lsb.huitral.ruka.lan +ipconfig /flushdns +``` +Alternatives : +- `Resolve-DnsName` (PowerShell) + +**DNS WSL** +``` +dig +short www.lsb.huitral.ruka.lan +ls -l /etc/resolv.conf +sudo tee /etc/wsl.conf <<'EOF' +[network] +generateResolvConf = false +EOF +``` +Alternatives : +- `nslookup` +- `host ` + -- cgit v1.2.3