2015-10-31 8 views
8

Mam ten kod, aby uruchomić zsh i zalogować jego wyjście do pliku wyjściowego.golang - różnica między os.stdout i multiwriter

package main 

import (
    "io" 
    "os" 
    "os/exec" 
) 

func main() { 

    cmd := exec.Command("zsh") 
    f, _ := os.Create("log.txt") 
    multiWriter := io.MultiWriter(os.Stdout, f) 
    cmd.Stdout = multiWriter 
    cmd.Stderr = os.Stderr 
    cmd.Stdin = os.Stdin 
    cmd.Run() 
}  
func haltOnError(err error) { 
    if err != nil { 
     panic(err) 
    } 
} 

gdy program wykonuje, wpisując wyjściu ls woli

foo 
bar 

natomiast jeśli pozwolę cmd.Stdout = os.Stdout, wyświetla poprawnie

foo bar 

Co prowadzi do różnic między os.Stdout i multiwriter?

+11

ta jest znana, ważne zachowanie. Program 'ls' używa funkcji' isatty' C do wyboru domyślnego formatu wyjściowego. Kiedy używasz 'io.MultiWriter',' isatty' zwraca 0, więc format wyjściowy 'ls' jest inny. –

+0

@TimCooper jest jakiś prosty sposób, aby pisarz w iść zachowywać się jak tty? Trochę google i dowiedzieć się pty ale nie wiem jak to działa. – boh

+0

@boh: dlaczego nie robić rzeczy na odwrót i nie zmuszać 'ls' do używania pożądanego formatu wyjściowego, niezależnie od możliwości wyjścia? Spróbuj 'ls -x',' ls -C' lub 'ls -1' – wldsvc

Odpowiedz

2

Na podstawie uwag @Time i @wldsvc

przyczyną problemu jest to, że isatty jest używany przez ls wybrać domyślny format wyjściowy, w tym przypadku zastosowanie io.MultiWriter i os.Stdout wyniku w różnych decyzji w oparciu na wyniku isatty.

Proponowane rozwiązanie było zmuszenie format wyjściowy ls za pomocą parametrów (man ls):

-C list by columns 
-x list by lines instead of columns 
-1 list one file per line 

(dokumentowanie odpowiedź jako pokaz cichy wysoko na liście nieodebranych)