Programme de la sortie perdu lorsqu'il est passé à travers PsExec
(C'est une question de mon collègue posté d'ailleurs, mais je pensais que je poste ici pour voir si je pourrais toucher un public différent.)
Bonjour à tous,
Je teste la possibilité d'écrire une petite application java la volonté d'utiliser Psexec pour le coup d'envoi de tâches à distance. Dans le cadre de tests de liaison de l'entrée standard stdin et stdout d'un programme java pour psexec je suis tombé sur une drôle de bug.
Mon programme de test est une base echo le programme. Il démarre un thread pour lire l'entrée standard stdin et puis les tuyaux de les lire directement la sortie de retour vers stdout. Lorsqu'il est exécuté sur la machine locale, pas de psexec, il fonctionne à merveille. Exactement comme il se doit.
Cependant, lorsque je l'appelle de PsExec la première fois, l'entrée est acheminée directement dans la sortie standard, il est perdu. Ce qui rend le bug vraiment bizzare, c'est que c'est seulement la première fois que l'entrée est acheminée directement dans stdout qu'il est perdu. Si la Chaîne d'entrée est ajoutée à une autre chaîne, il fonctionne très bien. Soit un littéral de Chaîne ou une variable Chaîne. Toutefois, si la Chaîne d'entrée est directement envoyé vers la sortie standard, il ne fonctionne pas. La deuxième fois, il est envoyé vers la sortie standard, il passe par l'amende et à chaque fois il y a après.
Je suis à une perte complète de ce qui se passe ici. J'ai essayé de tester pour chaque bug je pense. Je suis à court d'idées. Ai-je raté un ou est-ce juste quelque chose à l'intérieur de psexec?
Voici le code en question, c'est en trois classes (dont une qui implémente une interface, qui est une fonction unique interface).
La classe Principale:
public class Main {
public static void main(String[] args) {
System.out.println("Starting up.");
CReader input = new CReader(new BufferedReader(
new InputStreamReader(System.in)));
CEcho echo = new CEcho();
input.addInputStreamListener(echo);
input.start();
System.out.println("Successfully started up. Awaiting input.");
}
}
Le CReader classe qui est le thread qui lit l'entrée standard stdin:
public class CReader extends Thread {
private ArrayList<InputStreamListener> listeners =
new ArrayList<InputStreamListener>();
private boolean exit = false;
private Reader in;
public CReader(Reader in) {
this.in = in;
}
public void addInputStreamListener(InputStreamListener listener) {
listeners.add(listener);
}
public void fireInputRecieved(String input) {
if(input.equals("quit"))
exit = true;
System.out.println("Input string has made it to fireInputRecieved: "
+ input);
for(int index = 0; index < listeners.size(); index++)
listeners.get(index).inputRecieved(input);
}
@Override
public void run() {
StringBuilder sb = new StringBuilder();
int current = 0, last = 0;
while (!exit) {
try {
current = in.read();
}
catch (IOException e) {
System.out.println("Encountered IOException.");
}
if (current == -1) {
break;
}
else if (current == (int) '\r') {
if(sb.toString().length() == 0) {
//Extra \r, don't return empty string.
continue;
}
fireInputRecieved(new String(sb.toString()));
sb = new StringBuilder();
}
else if(current == (int) '\n') {
if(sb.toString().length() == 0) {
//Extra \n, don't return empty string.
continue;
}
fireInputRecieved(new String(sb.toString()));
sb = new StringBuilder();
}
else {
System.out.println("Recieved character: " + (char)current);
sb.append((char) current);
last = current;
}
}
}
}
La CEcho classe, qui est la classe que les tuyaux de retour sur la sortie standard:
public class CEcho implements InputStreamListener {
public void inputRecieved(String input) {
System.out.println("\n\nSTART INPUT RECIEVED");
System.out.println("The input that has been recieved is: "+input);
System.out.println("It is a String, that has been copied from a " +
"StringBuilder's toString().");
System.out.println("Outputting it cleanly to standard out: ");
System.out.println(input);
System.out.println("Outputting it cleanly to standard out again: ");
System.out.println(input);
System.out.println("Finished example outputs of input: "+input);
System.out.println("END INPUT RECIEVED\n\n");
}
}
Et enfin, voici le programme de la sortie:
>psexec \\remotecomputer "C:\Program Files\Java\jre1.6.0_05\bin\java.exe" -jar "C:\Documents et Settings\testProram.jar" PsExec v1.96 - Exécuter les processus à distance Copyright (C) 2001-2009 Mark Russinovich Sysinternals - www.sysinternals.com Le démarrage. Démarré avec succès. En attente d'entrée. Test Reçu caractère: T Reçu caractère: e Reçu personnage: s Reçu caractère: t Chaîne d'entrée a fait à fireInputRecieved: Test L'ENTRÉE DE DÉMARRAGE REÇU L'entrée qui a été reçu est: Test C'est une Chaîne, qui a été copié à partir d'un StringBuilder est toString(). La sortie proprement à la norme: La sortie proprement à la norme de nouveau: Test Fini les sorties d'entrée: Test FIN DE SAISIE REÇU
qu'il ne soit le nombre de caractères que vous avez saisie ou est-ce le comportement bizarre qu'avec 4-char cordes?
N'a pas d'importance combien de caractères que vous avez entrés.
J'espère que vous trouverez une solution à ce - si donc, assurez-vous de le poster!
Ouais... je souhaite qu'il y ait un moyen de les transférer à d'Alcon... c'est vraiment à sa question, il a juste ne le savais pas comment génial, DONC, a été jusqu'à ce que après que j'ai posté.
OriginalL'auteur mwalling | 2009-08-14
Vous devez vous connecter pour publier un commentaire.
avez-vous essayé de rediriger la sortie vers un fichier ( java... >c:\output.txt )? de cette façon, vous pouvez communiquer si tout va dans stdout et peut-être juste de les avoir consommés par les psexec
Nice appel, assurez-vous de suffisamment de psexec est de le manger. Ok, donc c'est un problème avec psexec. Maintenant, est-il un moyen de contourner cela?
Je l'accepte, car c'était la première personne qui a dit que c'était psexec de la faute, et la générosité doit aller quelque part.
OriginalL'auteur Niko
PsExec est de manger de la sortie. La prochaine chose intéressante pourrait être où il mange de la sortie. Vous pouvez vérifier ceci en obtenant une copie de Wireshark et de vérifier si la sortie en question est en traversant le réseau ou pas. Si elle ne l'est pas, puis elle se fait bouffer sur le côté éloigné. Si elle l'est, elle est consommée localement.
Pas que je sois vraiment sûr où aller à partir de là, mais de recueillir plus d'informations semble certainement comme un bon chemin à suivre...
OriginalL'auteur Jon Bright
Est
System.out
n'est pas configuré pour autoflush? Après la première impression essayerSystem.out.flush()
et de voir si la première ligne s'affiche sans plus de lignes imprimées.(oh oui, sérieusement, c'est "REÇU", pas "REÇU".)
et I suis censé être celui qui ne peut pas speel!
Vous êtes le seul qui ne peut pas expliquer :p je suis juste celui qui est paresseux.
OriginalL'auteur Mark
OK, j'ai été de penser à ce sujet pendant le week-end et je, puisque vous êtes le saut de machine à machine, je me demande si peut-être il ya un problème de CharSet? Peut-être que c'est de manger de la chaîne de la première heure et de traiter avec une autre page de code ou le jeu de caractères problème? Java est 16bit caractères normalement et windows est 8bit avec les pages de code ou de l'utf-8 ces jours-ci.
Toute chance local et à distance machines ont des jeux de caractères par défaut? Si vous envoyez des données localisées sur le net, il pourrait mal se conduire.
Je suis inquiet que PSExec a une idée différente de ce jeu de caractères, trop. Lorsque vous ajoutez le texte, il fonctionne parfaitement, mais si vous imprimez cru, il échoue la première fois... peut-être PSExec a pour développer son idée de jeu de caractères et perd la chaîne dans le processus? Certes, il est un "SWAG" mais une fois que vous commencez le passage des chaînes entre les tuyaux/ports de ce genre de choses arrive.
Je vais essayer de forcer un peu les jeux de caractères et de voir ce qui se passe.
Bon, essayé de forcer le BufferedReader qui est passée de CReader à utiliser le Latin-1 et de l'US-ASCII. Ni fait une différence. Ne veut pas dire qu'il n'est pas un jeu de caractères snafu, mais si ces deux ne fonctionnent pas alors j'ai un peu de doute que le fait de forcer un jeu de caractères va résoudre le problème 🙁 Sauf si il y a quelque part d'autre, j'ai besoin de le forcer.
OriginalL'auteur Mark
Ce que je vois lors de l'exécution de psexec est qu'il donne naissance à un enfant fenêtre pour faire le travail, mais ne pas revenir sur le programme de sortie à la fenêtre de la console. Je voudrais suggérer à l'aide de WMI ou une certaine forme de processus de windows API cadre d'acquérir un niveau de contrôle vous avez l'air de manque avec psexec. Sûrement java a un équivalent .Net du Système.Diagnotics.La classe de processus.
OriginalL'auteur Joe Caffeine
Peut-être vous pourriez essayer de passer une copie de la saisie de vos auditeurs:
J'ai eu des problèmes similaires avec les auditeurs, où le passé de la variable seraient vides, sauf si je l'ai fait passer une copie explicite.
OriginalL'auteur Shirkrin
Je n'ai pas forcément de réponse, mais certains commentaires peuvent s'avérer utiles.
Basé sur ces observations, je présume qu'il y a une différence entre le "Test" que vous avez reçu en entrée et le "Test" que vous avez entré dans le code. Quelle est la différence?
Vous pouvez tester mon dernier commentaire un peu plus à fond, en mettant cette ligne en haut de votre inputReceived fonction: 'input = "Test"'. Si elle fonctionne toujours, mais "Test" ne fonctionne pas à travers le flux de programme normal, il y a quelque chose de sournois et malveillant caché dans le texte reçu chaîne qui n'est pas dans la chaîne codée.
OriginalL'auteur John Fisher
Je suppose qu'il s'agit d'un faux octet dans il dans la préface de la T. Selon la documentation Javadoc, un InputStreamReader va lire un ou plusieurs octets, et de les décoder dans les personnages.
Vous pourriez avoir une séquence d'échappement ou les parasites des octets dans il y, se faisant passer pour un jeux de caractères multioctets.
Enregistrement rapide de voir si le "courant" est jamais > 128 ou < 33.
Que si vous avez utilisé un CharArrayReader pour obtenir octets individuels, sans aucun jeu de caractères de la traduction?
La théorie est que, lors de la première tentative de sortie de la Chaîne à l'aide println, c'est l'envoi d'un caractère d'échappement, de la sorte, manger le reste de la chaîne. Durant les derniers tirages, de Java ou le canal de réseau de traitement ou de les retirer, car il déjà eu cette séquence d'échappement, peut-être en modifiant le traitement d'une certaine façon.
Comme un autre nit, sb.toString() renvoie une nouvelle Chaîne de caractères, il est donc inutile d'appeler "new String(sb.toString())"
Je vais essayer de le vérifier et voir ce qui se passe.
OriginalL'auteur jmanning2k
J'ai eu le même problème et essayé plusieurs combinaisons de redirections.
C'est ce qui a fonctionné:
La Redirection.HÉRITER de processBuilder.redirectInput m'a l'manquant de la commande à distance de la sortie.
OriginalL'auteur farheen89
Comment êtes-vous de l'exécution de PsExec? Mon soupçon est que c'est un peu de code dans PsExec qui est en train de faire, suppression de l'écho, peut-être pour les fins de la protection d'un mot de passe. Un moyen pour tester cette hypothèse, il conviendrait de modifier ce code:
:
...provoquant la sortie (si je suis à droite):
En particulier, il est à noter que le apparemment supprimé la ligne est la première ligne qui se compose uniquement de
Test
- ce qui est exactement le texte que vous avez tout juste d'envoyer au système distant. Cela sonne comme PsExec de tenter de supprimer un système distant qui est l'écho de sa contribution à la production de sa propre production.Est le mot de passe de l'utilisateur sur la machine distante peut-être
Test
? Êtes-vous à l'aide de PsExec-p
paramètre? Êtes-vous en précisant-i
?Ne avoir un aller avec l'espace supplémentaire. Si cela fonctionne, alors que nous sommes très probablement sur la bonne voie avec echo-suppression. Si elle ne le fait pas, alors vous pouvez en toute sécurité ignorer moi 🙂
Pas de chance. Il mange encore de la sortie.
Oups, ne pas voir votre deuxième commentaire jusqu'à tout à l'heure quand j'ai commenté. C'était une bonne idée, mais ça n'a pas marché. Le test de sortie a suggéré quelques postes en bas a établi que c'est certainement psexec de manger de la sortie. Mais il ne semble pas avoir quelque chose à voir avec suppression de l'écho.
OriginalL'auteur Jon Bright
Je suis avec cette même question, et je me demande si cela a à voir avec la façon dont la fenêtre cmd et les tuyaux de travail windows alors que vous n'avez pas une vraie fenêtre de session. Le supprimé de sortie qui se passe quand tout nouveau processus est généré. Vous pensez que si vous frayer un processus que le stdout/stderr/stdin serait héritée du processus qui a donné naissance, après tout c'est ce qui arrive si vous frayer le processus à partir d'un fenêtre de commande et la sortie du nouveau processus est acheminée à l'arrière de votre propre console. Cependant, si quelque part dans l'héritage des tuyaux quelque chose devait mal se passer, comme, disons, ne passant pas par une FENÊTRE.GUI objet, car il n'y a pas de fenêtre, windows ne laissez pas le stdin/stdout/stdin être héréditaire. Peut-on faire une enquête ou d'ouvrir un windows ticket de support pour cela?
OriginalL'auteur Rusty Weber
Même problème ici, je vais à travers ce post, encore et encore ces jours-ci, en espérant que je puisse trouver une solution. Alors je décide que je dois abandonner psexec et de trouver une alternative. C'est donc la chose: PAExec. Fonctionne parfaitement pour l'obtention de la sortie de commande.
OriginalL'auteur jchen
Semble pas de solution facile. Mon travail autour de dans un récent projet est à l'aide de paexec.exe produit. Il capture de sortie/erreur facilement en JAVA(java 8), mais se bloque jusqu'à l'achèvement de la commande à distance de l'exécution. Lors de l'exécution de ce à l'intérieur d'un serveur sur le hébergé machine, je jette un nouvel enfant JVM processus à exécuter paexec.exe et à force de le tuer par son PID à la clôture afin de libérer toutes les ressources.
Si quelqu'un a une meilleure solution, s'il vous plaît poster.
OriginalL'auteur Herbert Wu