2017-08-02 5 views
0

Je suis en train d'appeler un script bash attendre de la manière suivante:attendre - Sortie directe de commande à distance pour le fichier local

#!/bin/bash 

mkfifo foobar 
expectScript > foobar & 
# other stuff that does stuff with foobar 

Que faut-expectScript à faire est de ssh dans un hôte distant. De là, il doit ssh dans un autre hôte distant. Ensuite, il doit changer d'utilisateur en root (la connexion root n'est pas autorisée). Ensuite, il doit émettre une commande (par exemple tail -f/var/log/messages) qui doit finalement être écrite dans foobar. Rien d'autre ne peut être écrit sur foobar, par ex. des invites de mot de passe ou des invites de commande. Seule la sortie de la commande peut être écrite sur foobar. J'ai la partie connexion du script fonctionne bien. Ce que je lutte avec, c'est comment faire en sorte que la sortie est écrite sur foobar, et de telle sorte que SIGINT va tuer la commande.

Voici ce que j'ai:

#!/usr/bin/expect -- 

set HOST1_USER myuser 
set HOST2_USER myotheruser 
set HOST1_PASSWORD mypassword 
set HOST2_PASSWORD myotherpassword 
set ROOT_PASSWORD anotherpassword 
set HOST1 192.168.0.5 
# HOST2 is only reachable from HOST1 
set HOST2 192.168.1.12 

global until_interrupt 
set until_interrupt 0 

set HOST1_PROMPT "CL-\\d.*#" 
set HOST2_PROMPT "\\\$ $" 
set ROOT_PROMPT "# $" 

log_user 0 

spawn ssh [email protected]$HOST1 
# ssh keys are exchanged with HOST1, so there is no need for password here 
    expect -re "$HOST1_PROMPT" { 
      send "ssh [email protected]$HOST2\n" 
      expect { 
        -re ".*ssword.*" { send "$HOST2_PASSWORD\n" } 
        -re ".*Are you sure you want to continue connecting.*" {send "yes\n"; exp_continue} 
      } 
    } 

    expect -re "$HOST2_PROMPT" { send "su\n" } 
    expect -re ".*ssword.*" { send "ROOT_PASSWORD\n" } 

    log_user 1 
    # nothing up to this point should have been sent to stdout 
    # now I want the output of the tail command to be sent to stdout 

    expect -re "$ROOT_PROMPT" { send "tail -f /var/log/messages\n" } 

    # I want to wait here until SIGINT is sent. There may be a better way than the traps below. 
    # Set a trap to watch for SIGINT 
    trap { 
      set until_interrupt sigint_detected 
    } SIGINT 

    while { $until_interrupt == 0 } { 
      #wait until sigint 
    } 

    send "\003" 
    # I think that is SIGINT, and that I'm sending it because I caught the first one in the trap. 

    trap { 
      exit 
    } SIGINT 

    set timeout 30 

    expect -re "$ROOT_PROMPT" { send "exit\n" } 
    expect -re "$HOST2_PROMPT" { send "exit\n" } 
    expect -re "$HOST1_PROMPT" { send "exit\n" } 
    # Fully exited 
+0

La plupart de ce script 'expect' peut être éliminé simplement en utilisant l'authentification par clé publique et le support de tunnel intégré' ssh'. – chepner

+0

Merci chepner, mais pas beaucoup peut être éliminé parce que sur HOST2 je dois exécuter la commande en tant que root (sudo ne fonctionnera pas), et HOST2 ne permet pas à root de se connecter sur ssh. Il est donc nécessaire de se connecter d'abord en tant qu'utilisateur non-root, puis de se connecter à root. J'ai implémenté la solution sur les hôtes où l'authentification par clé publique fonctionne, et c'est beaucoup plus facile. Mais pour ce serveur particulier, je ne vois pas comment cela pourrait fonctionner. –

+0

Si vous avez le mot de passe root, vous pouvez * configurer * sudo pour fonctionner. Et rien ne vous empêche de définir les ID utilisateur et les noms d'hôte corrects dans votre fichier de configuration local ssh'. – chepner

Répondre

0

Vous devriez être en mesure d'utiliser un expect pour l'écho du caractère de contrôle que vous envoyez à la télécommande (ou une autre chaîne ne pas être produit par votre commande tail -f) . Par exemple ce simple ssh exemple fonctionne pour moi (le -d est pour le débogage):

#!/usr/bin/expect -d 
log_user 0 
spawn ssh localhost 
expect " $ " 
send "tail -f /var/log/messages\n" 
log_user 1 
trap { send "\003" } SIGINT 
set timeout -1 
expect "\003" 
expect "$ " 
send "date\r" 
expect "$ " 

Si je lance cela, la redirection stdin à null, en arrière-plan de la coquille, je peux taper Ctrl-C et se termine proprement .

./prog </dev/null >/tmp/out &