Forum Linux.général Obtenir sortie de psql via ssh [résolu]

Posté par . Licence CC by-sa
Tags : aucun
1
31
août
2016

Bonjour,

Pour exécuter des requêtes SQL sur un serveur distant, je fais actuellement ceci en partant de mon PC perso :

$ ssh user@server1
user@server[database]/home/user$ psql
psql (9.4.4)
Type "help" for help.

database=# select tablename from pg_tables LIMIT 1;
tablename   
--------------
 pg_statistic
(1 row)

database=# 

J'aimerais, toujours depuis mon PC perso, lancer cette requête SQL, et obtenir sur la sortie standard de mon PC perso, le résultat de cette requête.

Sur un serveur sans pgbouncer :

$ ssh user@server1 psql << "END"
select tablename from pg_tables LIMIT 1;
END
psql: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

Sur un serveur avec pgbouncer :

$ ssh user@server2 psql << "END"
select tablename from pg_tables LIMIT 1;
END
psql: ERROR:  No such database: user

J'ai fais des recherches qui m'ont orienté vers la redirection de ports mais je ne parviens à rien :

$ ssh -L 63333:localhost:5433 user@server
user@server[database] /home/user $

Je suis aussitôt connecté comme si j'avais fait ssh user@server. Je ne sais que faire ensuite, ça ne m'avance à rien…

SmallFitz$ ssh -N -f -L 5433:localhost:5433 user@server
SmallFitz$ psql
psql: FATAL:  le rôle « SmallFitz » n'existe pas

Là je ne sais pas vraiment ce que ça fait, en tout cas mon prompt est libre mais je ne sais quoi faire ensuite…

Pourriez vous me venir en aide, me remettre sur les rails ?

Merci. :)

  • # inverse

    Posté par (page perso) . Évalué à 4. Dernière modification le 31/08/16 à 20:57.

    Et voilou !

    cat <<END | ssh $uat5_oltp psql
    select tablename from pg_tables LIMIT 1;
    END
    • [^] # Re: inverse

      Posté par . Évalué à 2. Dernière modification le 31/08/16 à 22:03.

      Pourrais-tu être plus explicite ? À priori il ne devrais y avoir aucune différence de comportement entre les deux versions.

      Je suppose que le problème pourrait être du à une différence entre le mode batch et interactif de ssh: peut-être un alias shell ou une variable d'environnement non passée…? Vu que la table ne s'appelle pas user, ben je dirais qu'une solution serait de demander à psql de connecter à la bonne base (option -d iirc, à vérifier).

      Note: une autre solution serait de configurer postgres pour écouter sur le réseau en TLS et configurer l'authentification de manière adéquate…

      • [^] # Re: inverse

        Posté par . Évalué à 1.

        s/table/db/

      • [^] # Re: inverse

        Posté par (page perso) . Évalué à 3. Dernière modification le 01/09/16 à 22:13.

        Pourrais-tu être plus explicite ? À priori il ne devrais y avoir aucune différence de comportement entre les deux versions.

        C'est peut être un bogue du bash mais la solution avec cat marche mais pas l'autre… Une autre soluce consiste à mettre des guillemets (pas testé ici) qui en gros donne une chaîne multi-lignes. On voit alors que le <<END est fait sur le serveur distant et non local.

        ssh user@server2 "psql << END
             select tablename from pg_tables LIMIT 1;
        END"
        • [^] # Re: inverse

          Posté par . Évalué à 2.

          parce que ta commande :

          ssh user@server2 "psql << END
          select tablename from pg_tables LIMIT 1;
          END"

          equivaut à lancer la commande :

          psql << END
          select tablename from pg_tables LIMIT 1;
          END

          sur le serveur final, ce qui n'est pas une commande valide

          d'apres la documentation la bonne commande serait celle-ci (note le \x obligatoire)

          psql <<EOF
          \x
          SELECT * FROM foo;
          EOF

          evidemment il faut aussi preciser la base de données, et d'autres options si necessaire

          plus d'infos ici
          https://www.postgresql.org/docs/9.4/static/app-psql.html

          • [^] # Re: inverse

            Posté par . Évalué à 1. Dernière modification le 02/09/16 à 00:22.

            Le \x n'a rien d'obligatoire: la documentation précise simplement que la seule façon de mélanger des méta-commandes (celles qui influencent le comportement du client, par exemple \x pour activer un formatage étendu) et des requêtes sql c'est de piper dans psql. Par opposition à utiliser l'argument -c; par exemple psql -d madb -c "select xxx;". L'argument à -c ne permet que l'utilisation de commandes sql. Dans le cas, si l'on désire modifier le comportement de psql, il faut soit configurer le fichier .psqlrc ou activer d'autres options de la ligne de commande (p.e. -x sur la ligne de commande est équivalent à \x dans psql).

            • [^] # Re: inverse

              Posté par . Évalué à 3.

              sauf que la documentation dit clairement que les fichiers psqlrc et .psqlrc sont ignorés quand on utilise l'option -c

              -c command
              --command=command
              Specifies that psql is to execute one command string, command, and then exit. This is useful in shell scripts. Start-up files (psqlrc and ~/.psqlrc) are ignored with this option.

              • [^] # Re: inverse

                Posté par . Évalué à 1.

                Oui quoi qu'il arrive des fichiers de conf ne sont pas lu.

          • [^] # Re: inverse

            Posté par . Évalué à 1.

            equivaut à lancer la commande :

            psql << END
            select tablename from pg_tables LIMIT 1;
            END

            sur le serveur final, ce qui n'est pas une commande valide

            Cette commande est valide chez moi :

            moi@pc_perso:~$ ssh user@server
            Last login: Mon Sep  5 15:46:11 2016 from 10.70.2.8
            user@server[database]
            /home/user $ psql << END
            > select tablename from pg_tables LIMIT 1;
            > END
              tablename   
            --------------
             pg_statistic
            (1 row)
            
        • [^] # Re: inverse

          Posté par . Évalué à 1.

          Es-tu l'auteur de l'entrée de ce forum ? J'ai vraiment du mal à croire que cat <<EOT | ssh cmd fonctionne différemment que ssh cmd <<EOT !

          • [^] # Re: inverse

            Posté par (page perso) . Évalué à 2.

            J'ai déjà lancé pas mal de jeux de commande à distance via ssh et la commande cat marche mais pas << ! Pourquoi ? Je ne sais pas du tout… Normalement, le << est géré par le shell donc ne devrait pas être transmis à la commande distante comme un post le dis ci-dessus.

            • [^] # Re: inverse

              Posté par (page perso) . Évalué à 2. Dernière modification le 05/09/16 à 16:18.

              En fait, je viens de tester, cela marche aussi… Je suis sur qu'il y a quelques années, cela ne marchait pas d'ou la forme avec cat que j'avais mis au point. Ceci dis, la seconde forme semble préférable et ne pose pas de problème de tty…

              # Forme 1
              ssh server << END
              ls   
              END
              
              # Forme 2
              ssh server 'bash' << END
              ls   
              END
      • [^] # Re: inverse

        Posté par . Évalué à 1.

        Je suppose que le problème pourrait être du à une différence entre le mode batch et interactif de ssh: peut-être un alias shell ou une variable d'environnement non passée…? Vu que la table ne s'appelle pas user, ben je dirais qu'une solution serait de demander à psql de connecter à la bonne base (option -d iirc, à vérifier).

        Salut,
        Bonne piste ! Merci ! :) Je vais me renseigner sur la conf qui se trouve sur le serveur.
        Voir s'il y a un alias ou quelque chose qui permet de ne donner aucun prédicat à la commande psql.

      • [^] # Re: inverse

        Posté par . Évalué à 1.

        Bingo ça venait bien de là.

        Mise en place de deux variables de test pour mettre en évidence l'importance des quotes simples sur les quotes double après la commande ssh.

        En local :

        moi@pclocal:~$ echo 'export test="Valeur locale !' >> .bashrc
        moi@pclocal:~$ exec bash
        moi@pclocal:~$ echo $test
        Valeur locale !

        Sur le serveur :

        moi@pclocal:~$ ssh user@server
        Last login: Mon Sep  5 16:21:00 2016 from 10.70.2.8
        user@server[database]
        /home/user $ echo 'export test="Valeur serveur !' >> .bashrc
        /home/user $ exec bash
        /home/user $ echo $test
        Valeur serveur !

        Maintenant test des DOUBLES quote

        moi@pcperso:~$ ssh user@server "echo $test"
        Valeur locale !

        Maintenant je teste les SIMPLE quote

        moi@pcperso:~$ ssh user@server 'echo $test'
        Valeur serveur !

        Conclusion : Il faut utiliser les simple quote.
        Maintenant recherche de la conf utilisée.

        moi@pclocal:~$ ssh user@server
        Last login: Mon Sep  5 16:21:00 2016 from 10.70.2.8
        user@server[database]
        /home/user $ echo $PGPORT
        5433
        /home/user $ exit
        logout
        moi@pcperso:~$ ssh user@server 'echo $PGPORT'

        Y'a donc bien un souci de definition de la variable $PGPORT.
        Une rapide recherche m'a permis de trouver que cette variable était définie dans le .bash_profile
        Il est donc nécessaire de le lire, de le sourcer avec . .bash_profile;

        moi@pcperso:~$ ssh $dev4_oltp '. .bash_profile; echo $PGPORT'
        5433

        Ca marche !
        Confirmé par :

        moi@pcperso:~$ ssh user@server '. .bash_profile; psql << END
        select tablename from pg_tables LIMIT 1;
        END'
          tablename   
        --------------
         pg_statistic
        (1 row)

        Merci à tous ! =)

      • [^] # Re: inverse

        Posté par . Évalué à 1. Dernière modification le 05/09/16 à 17:21.

        Maintenant l'incompréhension c'est pourquoi le .bash_profile n'est pas lu ???

        J'ai essayé un

        moi@pcperso:~$ ssh user@server 'exec bash; echo $PGPORT'

        Le bash a vraiment l'air de s'exécuter sur le server… Et ma sortie standart à l'air redirigée là bas, alors que mon entrée standard non (je crois ???)

        • [^] # Re: inverse

          Posté par . Évalué à 2.

          Maintenant l'incompréhension c'est pourquoi le .bash_profile n'est pas lu ???

          parce que .bash_profile est lu quand le bash est en mode 'interactif'
          ce qui n'est pas le cas quand tu fais un ssh user@server 'commande'

    • [^] # Re: inverse

      Posté par . Évalué à 1.

      Salut,

      Ca ne change rien j'ai la même erreur :

      cat <<END | ssh user@server psql
      select tablename from pg_tables LIMIT 1;
      END
      psql: ERROR:  No such database: user
      
  • # comprendre le tunnel ssh, ca aide

    Posté par . Évalué à 5.

    $ ssh -L 63333:localhost:5433 user@server
    user@server[database] /home/user $

    Je suis aussitôt connecté comme si j'avais fait ssh user@server. Je ne sais que faire ensuite, ça ne m'avance à rien…

    ben oui, tu as demandé à créer un tunnel 63333 depuis ta machine vers le localhost:5433 en passant par server
    c'est ce que tu as, il faut laisser ce terminal ouvert, pour maintenir le tunnel.

    maintenant il faut utiliser ce tunnel (qui soit dit en passant n'a pas de sens si tu as deja acces au port normal (5433) sur l'IP du serveur.

    pour utiliser ce nouveau port sur ta machine locale, il faut dire à psql de se connecter à localhost (ta machine), port 63333 (celui sur lequel est monté le tunnel)
    et ca ira vers le server, au travers SSH, a localhost (le server), port 5433 (celui de postgresql)

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.