Ouvrir une fenêtre sur un affichage X distant (pourquoi «Impossible d'ouvrir l'affichage»)?

81

Il était une fois,

DISPLAY=:0.0 totem /path/to/movie.avi

après que ssh 'ing sur mon bureau à partir de mon ordinateur portable provoque totem à jouer movie.avisur mon bureau.

Maintenant, cela donne l'erreur:

No protocol specified
Cannot open display:

J'ai réinstallé Debian Squeeze quand il est devenu stable sur les deux ordinateurs et je suppose que j'ai cassé la configuration.

J'ai googlé là-dessus et je ne peux pas comprendre ce que je suis censé faire.

(VLC a une interface HTTP qui fonctionne, mais ce n'est pas aussi pratique que ssh.)

Le même problème se pose lorsque j'essaie de l'exécuter à partir d'un travail cron.

Justin Cress
la source
1
Votre ordinateur distant affiche-t-il un fichier .Xauthority? L'autre question évidente est la suivante: votre serveur ssh et votre client sont-ils configurés pour autoriser le transfert X? Quelle commande avez-vous utilisé pour SSH?
Faheem Mitha
1
Est-ce que j'essaie de transmettre X? Je veux que la commande soit exécutée sur l'hôte, pas sur le client. Ma commande ssh est juste ssh me @ hôte localiser .Xauthority sur l'ordinateur hôte ne correspond à aucun fichier.
Justin Cress
Comme le suggère Faheem, le fait que votre problème totemne trouve pas votre cookie X constitue un changement important. Vous devez donc définir XAUTHORITYla valeur appropriée, c'est-à-dire la valeur de votre session normale sur votre bureau. Lire Linux: wmctrl ne peut pas ouvrir l’affichage lorsque la session est lancée via ssh + screen pour un fond d’arrière-plan; Voir aussi la réponse correspondante En tant que root, puis-je lancer un programme graphique sur le bureau d'un autre utilisateur? .
Gilles
1
d'accord, assis physiquement devant l'ordinateur et tapant echo $ XAUTHORITY donne / var / run / gdm3 / auth-pour-jcress-bb32gX / database dans la session ssh, taper echo $ DISPLAY = (le chemin ci-dessus) ne résout pas le problème
justin cress
1
Je blâme GDM3, pourquoi ne pouvaient - ils ont juste continué $XAUTHORITYà ~/.Xauthoritycomme tout le monde attend que ce soit.
Arrowmaster

Réponses:

78

(Adapté de Linux: wmctrl ne peut pas ouvrir l’affichage lorsque la session est lancée via ssh + screen )

AFFICHAGE ET AUTORITÉ

Un programme X a besoin de deux informations pour se connecter à un affichage X.

  • Il a besoin de l'adresse de l'écran, généralement :0lorsque vous vous connectez localement ou :10, :11etc. lorsque vous vous connectez à distance (mais le nombre peut changer en fonction du nombre de connexions X actives). L'adresse de l'affichage est normalement indiquée dans la DISPLAYvariable d'environnement.

  • Il a besoin du mot de passe pour l'affichage. Les mots de passe d'affichage X sont appelés des cookies magiques . Les cookies magiques ne sont pas spécifiés directement: ils sont toujours stockés dans des fichiers d'autorité X, qui sont une collection d'enregistrements de la forme «display :42a cookie 123456». Le fichier d'autorité X est normalement indiqué dans la XAUTHORITYvariable d'environnement. Si $XAUTHORITYn'est pas défini, les programmes utilisent ~/.Xauthority.

Vous essayez d’agir sur les fenêtres affichées sur votre bureau. Si vous êtes la seule personne à utiliser votre ordinateur de bureau, il est fort probable que le nom d'affichage le soit :0. Il est plus difficile de trouver l'emplacement du fichier d'autorité X, car avec gdm configuré sous Debian Squeeze ou Ubuntu 10.04, il se trouve dans un fichier portant un nom généré aléatoirement. (Vous n'aviez aucun problème auparavant, car les versions précédentes de gdm utilisaient le paramètre par défaut, à savoir les cookies stockés dans ~/.Xauthority.)

Obtenir les valeurs des variables

Voici quelques façons d'obtenir les valeurs de DISPLAYet XAUTHORITY:

  • Vous pouvez systématiquement démarrer une session écran à partir de votre bureau, peut-être automatiquement dans vos scripts de connexion (à partir de ~/.profile; mais ne le faites que si vous vous connectez sous X: test si DISPLAYest définie sur une valeur commençant par :(qui devrait couvrir tous les cas dans lesquels vous êtes susceptible de rencontrer)). Dans ~/.profile:

    case $DISPLAY in
      :*) screen -S local -d -m;;
    esac
    

    Ensuite, dans la session SSH:

    screen -d -r local
    
  • Vous pouvez également enregistrer les valeurs de DISPLAYet XAUTHORITYdans un fichier et les rappeler. Dans ~/.profile:

    case $DISPLAY in
      :*) export | grep -E '(^| )(DISPLAY|XAUTHORITY)=' >~/.local-display-setup.sh;;
    esac
    

    Dans la session SSH:

    . ~/.local-display-setup.sh
    screen
    
  • Vous pouvez détecter les valeurs de DISPLAYet à XAUTHORITYpartir d' un processus en cours. C'est plus difficile à automatiser. Vous devez déterminer le PID d'un processus connecté à l'affichage sur lequel vous souhaitez travailler, puis extraire les variables d'environnement de /proc/$pid/environ( eval export $(</proc/$pid/environ tr \\0 \\n | grep -E '^(DISPLAY|XAUTHORITY)=')¹).

Copier les cookies

Une autre approche (à la suite d’une suggestion de Arrowmaster ) est de ne pas essayer d’obtenir la valeur de $XAUTHORITYssh dans la session ssh, mais bien de faire en sorte que la session X copie ses cookies dans ~/.Xauthority. Comme les cookies sont générés à chaque fois que vous vous connectez, ce n'est pas un problème si vous conservez des valeurs périmées dans ~/.Xauthority.

Il peut y avoir un problème de sécurité si votre répertoire personnel est accessible via NFS ou un autre système de fichiers réseau permettant aux administrateurs distants de visualiser son contenu. Ils auraient quand même besoin de se connecter à votre machine, sauf si vous avez activé les connexions X TCP (Debian les a désactivées par défaut). Donc, pour la plupart des gens, cela ne s'applique pas (pas de NFS) ou ne pose pas de problème (pas de connexions X TCP).

Pour copier des cookies lorsque vous vous connectez à votre session de bureau X, ajoutez les lignes suivantes à ~/.xprofileou ~/.profile(ou à un autre script lu lors de votre connexion):

case $DISPLAY:$XAUTHORITY in
  :*:?*)
    # DISPLAY is set and points to a local display, and XAUTHORITY is
    # set, so merge the contents of `$XAUTHORITY` into ~/.Xauthority.
    XAUTHORITY=~/.Xauthority xauth merge "$XAUTHORITY";;
esac

¹ En principe, il manque une citation correcte, mais dans ce cas précis $DISPLAY, $XAUTHORITYil ne contient aucun métacaractère shell.

Gilles
la source
2
Une façon d'automatiser ceci serait de créer un programme ~/.xprofilequi ne devrait être exécuté que pendant la connexion X et le créer / mettre ~/.Xauthorityà jour avec les informations correctes. Un lien symbolique serait-il suffisant?
Arrowmaster
@Arrowmaster: C'est une bonne suggestion. Je n'y avais pas pensé. Cela ne fonctionnera pas dans tous les cas, par exemple si vous vous connectez à plus d'une session X (sur différents terminaux, avec vnc,…), mais c'est simple et il convient à une utilisation normale. Un lien symbolique est le meilleur moyen. Hmm, en fait, il existe un moyen plus simple et meilleur: vous pouvez copier les informations dans ~/.Xauthority.
Gilles
1
Est-ce que mettre quelque chose comme xauth extract - $DISPLAY | xauth -f "$HOME/.Xauthority" merge -pour ~/.xprofilerésoudre le cas de plusieurs $ DISPLAY?
Arrowmaster
@Arrowmaster: Quel problème voyez-vous avec plusieurs écrans? Bien que votre code soit en principe un peu plus propre, puisque vous n'extrayez que des informations sur l'affichage qui vous intéresse, je ne vois aucun inconvénient à une simple fusion dans le cas du demandeur, ni même en dehors de circonstances très inhabituelles.
Gilles
1
La lecture de l'environnement à partir d'un processus existant connecté à l'écran est inattendue pour être délicieusement perverse. J'approuve sans réserve. Unix.SE nécessite un badge Evil Genius ™ pour cela.
Derobert
19

J'ai résolu ce problème en ajoutant

xhost +si:localuser:$USER

à ~/.xprofile. Je ne sais pas si cela est totalement sûr (je serais très intéressé d’entendre ce que pensent des gens plus avertis), mais je suppose que c’est bien mieux que d’éteindre le contrôle d’accès (avec xhost +) comme il est communément suggéré google pour cette question.

Edam
la source
1
localuserles adresses interprétées par le serveur sont complètement sécurisées. Debian le fait même par défaut dans le cadre du processus de connexion (in /etc/X11/Xsession.d/35x11-common_xhost-local). Consultez la page de manuel Xsecurity pour plus de détails.
Sam Morris
Si vous êtes sur un réseau local, xhost +c'est probablement assez dans la plupart des cas ...
Alexis Wilke
Seriez-vous capable d'expliquer ce que cette commande signifie?
alpha_989
@ alpha_989: Cela signifie "Accorder l'accès [+] à toute application [utilisateur local] en cours d'exécution locale qui s'exécute en tant que moi [$ USER]." Le "si" est juste de la colle (voir xhost(1)et Xsecurity(7)pour la documentation). En soi, cette commande ne pas permettre à tout type d'accès à distance ou à la transmission X11 (pour lequel le mécanisme de « magic cookie » est généralement préférée sur xhost).
Kevin
7

Tu dois export DISPLAY=:0.0

se déplacer
la source
Non, Unix ne nécessite pas d'exportation lorsque la variable est écrite sur la même ligne. Cette variable est effective jusqu'à la fin de la ligne.
Alexis Wilke
En effet, vous avez raison.
asoundmove
Cette réponse est clairement fausse et devrait être supprimée.
Piotr Dobrogost
Je ne savais pas que taper DISPLAY =: 0.0 définirait le nom de la variable. Merci @asoundmove. Cependant, je pense que: 0,0 est la valeur de la variable DISPLAY à l’affichage du serveur. Si vous vous connectez à partir de Putty, la variable DISPLAY doit être égale ou supérieure à 10. il devrait donc être DISPLAY =: 10
alpha_989
3

Cela fonctionne pour moi, debian Wheezy -> ubuntu fidèle.

Remarque: dans ce cas, le serveur n’exécute pas de gestionnaire d’affichage, il s’agit d’une machine virtuelle «sans tête» sans carte graphique ni moniteur connecté.

bob@laptop:~$ grep -iB 1 tcp /etc/gdm3/daemon.conf
[security]
DisallowTCP = false
bob@laptop:~$ ssh -C -R 6000:127.0.0.1:6000 alice@server
X11 forwarding request failed on channel 0
alice@server:~$ export DISPLAY=:0.0
alice@server:~$ xterm

L’affichage X sur un ordinateur portable montre la sortie de xterm fonctionnant sur le serveur.

Déboguer en utilisant:

bob@laptop:~/tmp$ nc -v 127.0.0.1 6001
localhost [127.0.0.1] 6001 (x11-1) : Connection refused
bob@laptop:~/tmp$ nc -v 127.0.0.1 6000
localhost [127.0.0.1] 6000 (x11) open
alice@server:~$ nc -v 127.0.0.1 6000
Connection to 127.0.0.1 6000 port [tcp/x11] succeeded!*
alice@server:~$ strace xterm

strace va débiter des tonnes de détails sanglants sur ce qu’il fait, vous devriez être capable de deviner où il se bloque - en attente d’une connexion ou autre.

En une ligne ..

ssh -C -R 6000:127.0.0.1:6000 alice@server "DISPLAY=:0.0 xterm"
jmullee
la source