Java: Commandes Shell avec redirection
J'essaie d'exécuter la redirection dans le shell en utilisant java, mais j'obtiens un file1.txt
vide pour la commande: ls -all > file1.txt
.
Bien que ls -all
soit exécuté correctement.
commandLine
est de type String et a la commande que je voudrais exécuter.
par exemple String commandLine = "ls -all";
Extrait de code(C'est la section pertinente du code) :
StringBuilder output = new StringBuilder();
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(new String[]{"/bin/sh", "-c", commandLine});
process.waitFor();
try {
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
line = "";
while ((line = reader.readLine())!= null) {
output.append(line);
output.append("\n");
}
}
catch(Exception ex) {
ex.printStackTrace();
}
finally {
process.destroy();
}
Enfin, je traite la sortie de l'instance output
.
En outre, je veux exécuter la commande similaire à {[7] } mais cela me donne aussi une réponse vide !
1 answers
Réponse Courte
Vous lisez stdout
, qui est vide car vous avez redirigé stdout
vers /dev/null
. Utiliser getErrorStream()
au lieu de getInputStream()
pour obtenir stderr
.
stdout
et stderr
Il y a 2 flux de sortie de chaque processus, stdout
et stderr
. Dans le cas du curl -v http://www.centos.org
mentionné, les 2 flux de sortie seraient les flux suivants:
stdout
:
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.6.3</center>
</body>
</html>
stderr
:
* Rebuilt URL to: http://www.centos.org/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 85.12.30.226...
* Connected to www.centos.org (85.12.30.226) port 80 (#0)
> GET / HTTP/1.1
> Host: www.centos.org
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.6.3
< Date: Thu, 19 May 2016 15:31:03 GMT
< Content-Type: text/html
< Content-Length: 184
< Connection: keep-alive
< Location: https://www.centos.org/
<
{ [184 bytes data]
100 184 100 184 0 0 1184 0 --:--:-- --:--:-- --:--:-- 1187
* Connection #0 to host www.centos.org left intact
Le >
opérateur de redirection uniquement stdout
, mais stderr
sera intact.
Exécution dans le terminal
Dans les terminaux, vous voyez généralement stdout
et stderr
mélangés. Donc, si vous exécutez curl -v http://www.centos.org > /dev/null
, puis stdout
serez redirigé vers /dev/null
, mais vous aurez quand même la sortie de stderr
. C'est ce que vous observez, quand vous dites que "exécuter la même commande bash donne [...] sortie."
Exécution depuis Java
L'exécution d'une commande à partir de Java, en revanche, gardera les deux flux séparés. Le flux stdout
peut être obtenu en utilisant process.getInputStream()
, et stderr
peut être obtenu en utilisant process.getErrorStream()
.
Vous utilisez l'ancien (stdout
), mais puisque stdout
est redirigé vers /dev/null
dans votre exemple (curl -v http://www.centos.org
), il n'est pas surprenant que vous ne voyiez aucune sortie.
La seule sortie que vous pourriez obtenir serait stderr
. Pour cela, vous devez remplacer process.getInputStream()
par process.getErrorStream()
.
Vide file1.txt
Vous indiquez dans les commentaires que le fichier file1.txt
est vide après avoir exécuté une commande comme celle-ci ls -all > file1.txt
à partir de Java.
La raison la plus probable est que l'exécution de ls
a effectivement échoué, mais vous ne voyez pas le message d'erreur car il est imprimé sur stderr
- que vous ne lisez jamais. Vous indiquez que la même commande fonctionne correctement dans le terminal, mais que les environnements d'exécution sont différents (variables d'environnement différentes, répertoire de travail différent, etc.), ce qui peut faire échouer la même commande. Alors lisez stderr
pour obtenir le message d'erreur.
Une autre raison possible pour un vide file1.txt
est que vous vérifiez un fichier différent car le répertoire de travail vous est inconnu. M'est arrivé plus d'une fois que j'ai vérifié le fichier incorrect! Vérifiez l'horodatage pour vous assurer que c'est le bon fichier.