1

Why is there no output? The goal is to pipe telnet through tee with this command:

sh -c telnet rainmaker.wunderground.com 3000 | tee weather.txt

For the purpose of seeing telnet output and logging server responses with Java. (While there are telnet libraries I'm trying to use the system telnet with exec, or similar, and not a library.)

The command is being echoed correctly below, yet no output shows:

thufir@mordor:~$ 
thufir@mordor:~$ java -jar NetBeansProjects/T/dist/T.jar 
Apr 05, 2016 4:36:56 AM net.bounceme.mordor.telnet.Main run
INFO: starting..
Apr 05, 2016 4:36:56 AM net.bounceme.mordor.telnet.Telnet <init>
INFO: connecting..
Apr 05, 2016 4:36:56 AM net.bounceme.mordor.telnet.PropertiesReader getConnection
INFO: starting..
Apr 05, 2016 4:36:56 AM net.bounceme.mordor.telnet.PropertiesReader getConnection
INFO: {weather.port=3000, weather.host=rainmaker.wunderground.com}
Apr 05, 2016 4:36:56 AM net.bounceme.mordor.telnet.Telnet getAddress
INFO: sh -c telnet rainmaker.wunderground.com 3000 | tee weather.txt
a
b
c
^CApr 05, 2016 4:37:01 AM net.bounceme.mordor.telnet.Telnet read
SEVERE: exiting.. 130
thufir@mordor:~$ 

Also, there's no weather.txt being created:

thufir@mordor:~$ 
thufir@mordor:~$ nl weather.txt
nl: weather.txt: No such file or directory
thufir@mordor:~$ 

code:

package net.bounceme.mordor.telnet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Telnet {

    private final static Logger LOG = Logger.getLogger(Telnet.class.getName());

    public Telnet() {
        LOG.info("connecting..");
    }

    private String getAddress() {
        Properties props = PropertiesReader.getConnection();
        String host = props.getProperty("weather.host");
        String port = props.getProperty("weather.port");
        String tee = " | tee weather.txt";
        String address = "sh -c telnet " + host + " " + port + tee;
        LOG.info(address);
        return address;
    }

    private void read(Process process) throws IOException, InterruptedException {
        BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = null;
        while ((line = input.readLine()) != null) {
            System.out.println(line);
        }
        int exitVal = process.waitFor();
        LOG.log(Level.SEVERE, "exiting.. {0}", exitVal);
    }

    private void useProcessBuilder() throws IOException, InterruptedException {
        LOG.info("using ProcessBuilder..");
        ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "-c", getAddress());
        Process process = processBuilder.start();
        BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = null;
        while ((line = input.readLine()) != null) {
            System.out.println(line);
        }
        int exitVal = process.waitFor();
        LOG.log(Level.SEVERE, "done {0}", exitVal);
    }

    public void tryProcessBuilder() {
        try {
            useProcessBuilder();
        } catch (IOException | InterruptedException ex) {
            Logger.getLogger(Telnet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void connect() throws IOException, InterruptedException {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec(getAddress());
        read(process);
    }

    public void tryConnect() {
        try {
            connect();
        } catch (IOException | InterruptedException ex) {
            Logger.getLogger(Telnet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

While it's possible to generate output, by leaving off the pipe to tee, that doesn't solve the problem of using tee with telnet.

see also:

The solution to the pitfall was to simply control the redirection by handling the external process's standard output stream separately from the Runtime.exec() method.

http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2

Thufir
  • 8,216
  • 28
  • 125
  • 273
  • Can you try [Runtime.html#exec](https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec(java.lang.String[])) – seenukarthi Apr 05 '16 at 10:27
  • @KarthikeyanVaithilingam very curious comment here: http://stackoverflow.com/a/19383655/262852 I made a follow up question: http://stackoverflow.com/questions/36429067/sending-a-cmdarray-for-exec-to-process-hello-world but haven't examined the source code for `exec` directly. Can you elaborate? – Thufir Apr 05 '16 at 14:21

1 Answers1

1

The only thing that understands | is a shell. You need to exec a shell to understand this piped command.

user207421
  • 305,947
  • 44
  • 307
  • 483