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
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
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. –
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