Univers Libre

Passer root sans terminal

Written on 26 January 2012, 00:00 EST
Tags: ssh, sudo, sysadmin.

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 :

#!/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.