D'accord, alors je suis nouveau à Ruby et j'ai un fond fort à bash / ksh / sh.
Ce que j'essaie de faire est d'utiliser une boucle simple pour exécuter une commande sur plusieurs serveurs. Dans Bash, je le ferais comme: p> etc / server_list est juste un fichier qui ressemble à: p> i Je ne peux pas sembler obtenir ce droit dans Ruby. C'est ce que j'ai jusqu'à présent: p> Je reçois ces erreurs maintenant: p> Le fichier est acheté Correctement, j'utilise le chemin relatif, car je suis assis dans le répertoire sous etc / (non / etc, j'exécute cette sortie d'un répertoire de script où je conserve le fichier dans un sous-répertoire appelé etc.) p> p>
5 Réponses :
La construction la plus courante que je vois lors de la mise en ligne d'itération d'un fichier est la suivante: pour développer sur ce qui précède avec d'autres informations plus générales rubis ... Cette syntaxe équivaut à : p> Quand j'ai été introduit pour la première fois à Ruby, je n'avais aucune idée de ce que le | f | et | ligne | Syntaxe signifiait. Je savais quand l'utiliser et comment cela a fonctionné, mais pas pourquoi ils choisissent cette syntaxe. À mon avis, c'est l'une des choses magiques sur Ruby. Cette syntaxe simple ci-dessus cache-t-elle un concept de programmation très avancé juste sous votre nez. Le code imbriqué à l'intérieur de la "fin" / "fin" ou {} est appelé un bloc. Et vous pouvez considérer cela une fonction anonyme ou une Lambda. Le | f | et | ligne | La syntaxe est en fait juste la poignée du paramètre transmis au bloc de code par le parent exécutant. p> dans le cas de fichier.Open (), la fonction anonyme prend un seul argument, qui est la poignée. À l'objet IO du fichier sous-entraillant. p> Dans le cas de chaque_line, il s'agit d'une fonction d'interactivité qui est appelée une fois pour chaque ligne. La | ligne | est simplement une poignée de variable aux données qui sont transmises avec chaque itération de la fonction. p> oh, et une bonne chose à propos de FILE.Open est-il automatiquement ferme le fichier à la fin. EDIT: P> L'erreur que vous obtenez maintenant suggère que l'appel SSH n'apprécie pas l'espacement supplémentaire (Newline) à la fin de la chaîne. Pour résoudre ce problème, effectuez simplement un P> Net::SSH.start(line.strip, 'andex') do |ssh|
end
Belle explication. J'ajouterais simplement que bien que chaque_line code> est plus explicite (comme vous l'appelez sur un objet de fichier), chaque code> fonctionne également. J'ai tendance à l'utiliser - moins de taper et cela me rappelle qu'un fichier peut être traité comme une gamme de lignes.
En fait, une dernière chose: c'est une convention et non une règle, mais {...} code> a vraiment tort pour moi pour un bloc multiligne.
@Telemachus ouais, convenu - do / fin pour Multilignes et {} pour une seule ligne semble être la norme tacite. Une seule ligne do / extrémité est encore plus laide que les crochets multilignes!
Modifier B>: Dans les versions plus récentes de Ruby, Chaque code> ne fonctionne plus. Vous devez expliquer explicitement chaque_line code>. Alors ignore que (maintenant) de mauvais avis de moi.
Utiliser fichier.foreach code>:
Net::SSH.start(line.chomp, 'andex') do |ssh|
Whoops .. n'a pas vraiment format correctement. Permettez-moi de mettre à jour le message d'origine.
Mise à jour du message d'origine, je semble avoir la même erreur avec chaque méthode que vous avez affichée.
Tous les contenus du fichier seront-ils chargés en mémoire? ou seulement une ligne à la fois? I.E. Pourriez-vous utiliser ce code si vous aviez un CSV de 80 Go?
@Zachsmith je ne crois que une ligne à la fois. Vous ne construisez pas une matrice réelle (ou une autre structure de données) chargée de la totalité du fichier en mémoire à la fois.
lire dans des lignes d'un fichier est une opération courante et Ruby a un moyen facile de le faire:
servers = File.readlines('/etc/SERVER_LIST')
servers.each {|s|
Net::SSH.start(s, 'andex') {|ssh| puts ssh.exec!("ls -l") }
}
Vous peut I> faire cela, mais je ne le ferais pas. Tout d'abord, si le fichier est très important, alors Readlines code> sera un coup de mémoire. Deuxièmement, dans un cas comme celui-ci, il n'est pas nécessaire de créer un tableau comme des serveurs code> code>. Il suffit de nourrir le fichier un bloc (comme quelques-uns d'entre nous dans d'autres réponses) et opérez sur les lignes lorsque vous les obtenez. Aucun tableau permanent n'est nécessaire.
@ Telemachus - Depuis qu'il a mentionné, il était un débutant rubis, je viens de choisir la méthode la plus simple à lire et à comprendre (un seul bloc, le fichier ouvert / fermé pris en charge de manière transparente). Cependant, vous êtes correct que cela lira dans l'ensemble du fichier avant de le traiter. Sur quelque chose de plus qu'une simple liste comme celle mentionnée par l'OP, cela peut facilement être un porc de performance.
L'OP utilise Net :: Ssh pour faire des opérations à distance, le coût de la lecture de la lecture de l'ensemble du fichier n'est pas une préoccupation: un fichier suffisamment grand pour prendre toute une journée à traiter sera confortablement en mémoire.
Je pense que c'est ce que vous voulez pour le la méthode de chaque_line inclut le "\ n", et la chompe le supprimera. P> dans 'Initialiser': nouvelle ligne à la fin du nom d'hôte (SocketError) Code> Erreur: P>
net :: ssh.start (ligne.chomp, 'andex') code> p>
En plus de ce que d'autres ont dit, je veux juste souligner que pour que les boucles ne soient pas beaucoup utilisées dans Ruby. La méthode
chaque code> est utilisée plus souvent.Ajouter un
Chomp code> pour vous débarrasser de la nouvelle ligne. Je vais mettre à jour ma réponse.faire une ligne.Strip pour dépouiller les espaces de la chaîne. Mise à jour de ma réponse ci-dessous avec cet addenda
Je signalerai qu'il y a une meilleure façon de le faire dans Bash:
pendant que le serveur de lecture; faire ...; fait