mtr
mtr copied to clipboard
Why read pipe nothing in Go, but ok in Java?HELP!!!
Go
package main
import (
"bufio"
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("mtr", "-p", "-c", "10", "www.qq.com")
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(err)
}
if err := cmd.Start(); err != nil {
fmt.Println(err)
}
go func() {
scr := bufio.NewScanner(stdout)
for {
if scr.Scan() {
fmt.Println(scr.Text())
}
if scr.Err() != nil {
return
}
}
}()
if err := cmd.Wait(); err != nil {
fmt.Println(err)
}
}
Java
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec(new String[]{"mtr", "www.qq.com", "-p", "-c", "10"});
try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
}
} catch (Exception err) {
err.printStackTrace();
}
}
}
It looks like mtr got stuck on stdin in your Go program, so just open stdin and keep it opened, and you will get something in output (stdout or stderr)
Thank you very much for your comment, but I don't seem to understand what you mean, can you be more clear, thks.
He is suspecitng that the subcommand mtr doesn't have stdin connected and that this messes something up. There should be a cmds.stdin = "/dev/null" that you can add. (but I've never written a line of "go" in my life, so you'll have to figure out the exact syntax on your own.)
@rewolff not totally, I suppose /dev/null stdin is already present in that go code
it can be emulated with
mtr -p -c 10 www.qq.com </dev/null
@billcoding try this
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("mtr", "-p", "-c", "10", "www.qq.com")
stdin, err := cmd.StdinPipe(); if err != nil { fmt.Println(err); os.Exit(1); }
stdout, err := cmd.StdoutPipe(); if err != nil { fmt.Println(err); os.Exit(1); }
stderr, err := cmd.StderrPipe(); if err != nil { fmt.Println(err); os.Exit(1); }
defer stdin.Close()
if err := cmd.Start(); err != nil { fmt.Println(err); os.Exit(1); }
go func() {
scr := bufio.NewScanner(stdout)
for {
if scr.Scan() {
fmt.Println(scr.Text())
}
if err := scr.Err(); err != nil {
fmt.Println(err)
return
}
}
}()
go func() {
scr := bufio.NewScanner(stderr)
for scr.Scan() {
fmt.Println("Err:", scr.Text())
}
}()
if err := cmd.Wait(); err != nil {
fmt.Println(err)
}
}
I have tried it and it's Ok! But what I don't understand is, why should you care about the stdin pipe?
I don't know and I don't care enough to try figure it out.
Usually some library that is linked (but maybe not used at the moment) that expects something (anything!) to be connected.
Or an "open" that usually gives file descriptor 4 or 5 that now suddenly gives file descriptor 0 and the error check is that the fd must be > 0...
On Thu, Sep 29, 2022 at 06:05:37AM -0700, yvs2014 wrote:
@rewolff not totally, I suppose /dev/null stdin is already present in that go code it can be emulated with
mtr -p -c 10 www.qq.com </dev/null
Yeah! That's the easier mod that us? non-GO people could write to get
the same effect. My hypothesis is that go would not connect /dev/null,
but simply not open the fd. That fd is then free and can be reassigned
to the first open. And a read of
@billcoding
why should you care about the stdin pipe?
mtr is an interactive program, it tests stdin for input, for example if you press 'q' mtr quits, and so on. Non-interactive modes: -r or -w options, and maybe a couple more. Mtr with "-p" works in the interactive mode.
@rewolf I didn't get that far, it's for golang pandits, easier to open stdin and forget about it
On Fri, Sep 30, 2022 at 04:39:13AM -0700, yvs2014 wrote:
@rewolf I didn't get that far, it's for golang pandits, easier to open stdin and forget about it
But figuring out what the failure mode is helps us avoid the problem in the future.
@rewolff if something is wrong with stdin, there are two options for split mode as far as I can see:
- print an error and exit
- automatically switch to non-interactive mode
the second one works like
% mtr -p localhost </dev/null
split_open(): tcgetattr(): Inappropriate ioctl for device
non-interactive mode is ON
1 127.0.0.1 0.0 1 1 0.1 0.1 0.1
1 127.0.0.1 0.0 1 1 0.1 0.1 0.1
1 127.0.0.1 0.0 1 1 0.1 0.1 0.1
1 127.0.0.1 0.0 1 1 0.1 0.1 0.1
1 127.0.0.1 0.0 1 1 0.1 0.1 0.1
1 127.0.0.1 0.0 2 2 0.1 0.1 0.1
^C
https://github.com/yvs2014/mtr/commit/ed8a8e60dce467283655fce32c29313fc3390cd0
@yvs2014 i think you meant @rewolff 👍
Sorry, my typo, fixed