Passer root sans terminal
Dans certains rares cas, on peut vouloir exécuter des commandes en tant que root sans avoir la possibilité d’allouer un terminal sur la machine en question.
Pour ceux qui aiment bien lire la fin en premier, je mets la fin au début
:
echo "mypassword" |sudo -S id
Pour illustrer le problème, prenons un cas concret qui m’est arrivé.
Un serveur s’est soudainement mis dans un état bizarre, à savoir que tout marchait, les processus déjà en cours continuaient de s’exécuter, d’autres processus pouvaient se créer, mais certaines choses ne marchaient pas, notamment l’allocation de pseudo-terminaux (les /dev/pts/*) ; si je tente une connexion SSH au serveur, le serveur répond bien, l’authentification se fait, et au moment d’avoir mon prompt, la connexion se freeze.
Après divers tests, je m’aperçois qu’en passant directement une commande à ssh, ça marche :
ssh serveur-foireux dmesg
La différence vient du fait que dans le deuxième cas, ssh n’ouvre pas de pseudo-terminal sur le serveur distant, puisqu’il se contente de récupérer directement stderr et stdout.
On peut faire en sorte de se connecter sans allouer de terminal sur le serveur avec l’option -T de la commande ssh :
-T Disable pseudo-tty allocation.
On a ainsi un shell qui s’exécute sur la machine, et on récupère la sortie brute de stderr et stdout (pas de prompt, d’édition de la commande en cours, etc…). Pareil pour stdin, ce qui fait que les commandes sudo ou su retournent une erreur, étant donné qu’elles font une manipulation spécifique sur stdin (pas d’echo pour la saisie du mot de passe). De ce fait, on est un peu coincé pour passer root.
Il existe une solution (que j’ai bien sûr trouvé après avoir brutalement redémarrer le serveur), une simple option à sudo qui permet de lire le mot de passe depuis stdin. Et là, pas besoin d’exécuter la commande dans un terminal donc !
echo "mypassword" |sudo -S id [sudo] password for rdessort: uid=0(root) gid=0(root) groupes=0(root)
Et comme cela affiche votre mot de passe en clair sur l’écran, voici un petit script pour améliorer la chose :
1 2 3 4 5 6 | #!/bin/bash echo -n "Enter password: " read -s passwd ssh serveur-foireux "echo $passwd |sudo -S id" |
Une autre application probablement beaucoup plus courante pourrait être de pouvoir scripter des commandes nécessitant d’être root sur le serveur. Notamment exécuter la même commande sur plusieurs dizaines de serveurs d’affilée.
autoconfiguration IPv6 et forwarding
Ayant enfin activé l’IPv6 sur mon serveur (IPv6 day oblige) ces derniers jours, je me suis heurté à un problème lié au forwarding lorsque l’hôte et en mode autoconfiguration.
L’hôte en question fait tourner des environnements virtuels à l’aide d’OpenVZ, ce qui m’oblige donc à rajouter ceci dans mon /etc/sysctl.d/openvz.conf pour qu’ils puissent avoir une chance de sortir sur Internet :
1 | net.ipv6.conf.all.forwarding=1 |
Cependant cela entraine la désactivation de l’autoconfiguration « stateless » de l’hôte, c’est à dire qui n’est plus capable de prendre une IP automatiquement, ni de positionner sa route par défaut.
Je ne rentrerai pas dans les détails de pourquoi c’est comme ça, n’ayant pas trouvé d’explications sur le sujet, mais je suppose que le noyau doit ainsi transférer tous les paquets NDP sur sa seconde interface, même s’il ne devrait pas car ces paquets ne sont pas censés traverser les routeurs. Bref si quelqu’un a une explication, qu’il n’hésite pas !
Une fois qu’on sait ça, rien de compliqué (le plus dur en fait est de se rendre compte que le forwarding désactive l’autoconfiguration de l’hôte). On peut configurer l’interface de manière statique dans /etc/network/interfaces (pour Debian et dérivés) :
1 2 3 4 5 | iface eth0 inet6 static
address 2a01:e35:2e31:da50:1e6f:65ff:fe54:5c96
netmask 64
up route -A inet6 add default gw fe80::224:d4ff:feb4:f9b6 dev eth0 metric 1
down route -A inet6 del default gw fe80::224:d4ff:feb4:f9b6 dev eth0 metric 1 |
Source de l’image : http://www.potaroo.net/presentations/2008-11-17-ipv6-failure.pdf (http://www.potaroo.net)
Lighttpd et encodage de fichiers texte
Voici une petite astuce pour résoudre le problème d’encodage des fichiers servis par Lighttpd, dans le cas où les fichiers en questions sont en UTF-8.
En guise de rappel, Lighttpd est un serveur web simple, léger mais puissant par rapport à Apache. Voir ici pour plus d’info.
Par défaut l’encodage des fichiers n’est pas précisé dans le champ « Content-Type », comme le montre une requête HTTP HEAD :
$ HEAD http://univers-libre.net/plop.txt 200 OK Connection: close Date: Fri, 27 May 2011 20:23:14 GMT Accept-Ranges: bytes ETag: "1885714849" Server: lighttpd/1.4.28 Content-Length: 7767 Content-Type: text/plain Last-Modified: Sun, 02 May 2010 09:34:31 GMT Client-Date: Fri, 27 May 2011 20:20:53 GMT Client-Peer: 192.168.0.60:80 Client-Response-Num: 1
Dans la majeure partie des cas, on s’en fou grave car l’encodage est précisé dans la balise HTML , et le client interprète donc bien le texte comme étant de l’UTF-8 (ou ce que vous voulez). Oui mais justement, lorsqu’on veut que Lighttpd serve de bêtes fichiers texte, nous n’avons plus cette balise pour nous aider. Il faut donc forcer le champ Content-Type pour rajouter charset=utf8 à la fin.
Avec Apache, cela se fait en rajoutant la directive AddDefaultCharset. Sous Lighty, il faut redéfinir le type MIME en question, de cette manière :
1 | mimetype.assign += ( ".txt" => "text/plain; charset=utf8" ) |
Attention, petite particularité sous Debian (ce n’est peut-être pas spécifique à Debian non plus), les types MIME sont générés par un script perl /usr/share/lighttpd/create-mime.assign.pl, appelé dans la conf de lighttpd. Il faut donc bien faire attention à rajouter la ligne de conf ci-dessus *après* cette ligne :
1 | include_shell "/usr/share/lighttpd/create-mime.assign.pl" |
Page de status de php-fpm et Lighttpd
Récemment, j’ai mis en place php5-fpm en remplacement de fastcgi sur mon Lighttpd. Je rencontrais des problèmes de lenteurs de manière aléatoire lors de l’appel à un process PHP (même pour exécuter un
echo "foo") que je n’ai pas trop réussis à débuguer.
Mais bref, là n’est pas le sujet. J’ai entendu beaucoup de retours positifs sur php-fpm, ce qui m’a convaincu de le le mettre en place.
Je n’ai pas encore eu trop l’occasion de regarder en détail la conf, celle par défaut marche sans soucis. Je vais donc pour l’instant juste vous faire part d’un petit détail lié à la page de status de php-fpm et Lighttpd (mais qui doit probablement impacter d’autres serveurs web).
En fait, par défaut elle ne marche pas (erreur 404). Dans la conf, il est dit :
; Note: The value must start with a leading slash (/). The value can be
; anything, but it may not be a good idea to use the .php extension or it
; may conflict with a real PHP file.
Soit, mais rien est dit quant à la configuration du serveur web devant.
J’ai mis un petit moment à comprendre, donc je vous donne l’astuce pour éviter de se prendre la tête.
Voici le petit bout de conf à rajouter dans Lighty :
1 2 3 4 5 6 7 | fastcgi.server += (( "/status" => ( "host" => "127.0.0.1", "port" => 9000, "check-local" => "disable" ) )) |
Et une petite explication sur le problème (qui est en fait tout à fait logique) :
Par défaut le serveur web ne peut pas savoir que php-fpm fournit la page /status. Pour lui, si pas de fichier nommé status, il s’arrête là en renvoyant une 404. Il faut donc forcer Lighttpd à passer cette URL à php-fpm (comme si c’était un .php), et sans vérifier si le fichier existe bien sur le système de fichier.

