Przekieruj stderr i stdout w Bash


678

Chcę przekierować zarówno stdout, jak i stderr procesu do jednego pliku. Jak to zrobić w Bash?


2
Chciałbym powiedzieć, że jest to zaskakująco przydatne pytanie. Wiele osób nie wie, jak to zrobić, ponieważ nie muszą tak często robić i nie jest to najlepiej udokumentowane zachowanie Bash.
Robert Wm Ruedisueli

2
Czasami dobrze jest zobaczyć wynik (jak zwykle) ORAZ przekierować go do pliku. Zobacz odpowiedź Marko poniżej. (Mówię to tutaj, ponieważ łatwo jest spojrzeć na pierwszą zaakceptowaną odpowiedź, jeśli jest to wystarczające do rozwiązania problemu, ale inne odpowiedzi często dostarczają przydatnych informacji.)
jvriesem

Odpowiedzi:


761

Spójrz tutaj . Powinien być:

yourcommand &>filename

(przekierowuje zarówno nazwę pliku, jak stdouti stderrnazwę pliku).


29
Ta składnia jest przestarzała zgodnie z Wiki Bash Hackers . Czy to jest
Salman von Abbas,

20
Według wiki.bash-hackers.org/scripting/obsolete wydaje się, że jest przestarzały w tym sensie, że nie jest częścią POSIX, ale strona podręcznika użytkownika bash nie wspomina o usunięciu go z bash w najbliższej przyszłości. Strona man określa preferencje dla „&>” over ”> &”, które w przeciwnym razie są równoważne.
chepner

13
Myślę, że nie powinniśmy używać &>, ponieważ nie ma go w POSIX, a popularne powłoki takie jak „dash” nie obsługują go.
Sam Watkins,

27
Dodatkowa wskazówka: Jeśli używasz tego w skrypcie, upewnij się, że zaczyna się on #!/bin/bashod #!/bin/sh, ponieważ in wymaga bash.
Tor Klingberg

8
Lub & >>, aby dołączyć zamiast zastąpić.
Alexander Gonchiy

448
do_something 2>&1 | tee -a some_file

Spowoduje to przekierowanie stderr do stdout i stdout do some_file i wydrukowanie go do stdout.


16
W systemie AIX (ksh) Twoje rozwiązanie działa. Akceptowana odpowiedź do_something &>filenamenie. +1.
Wstrzymano

11
@Daniel, ale to pytanie dotyczy konkretnie bash
John La Rooy,

3
Mam Ambiguous output redirect.pomysł, dlaczego?
Alexandre Holden Daly

1
Mam skrypt ruby ​​(którego nie chcę w żaden sposób modyfikować), który wyświetla komunikaty o błędach pogrubioną czerwoną czcionką. Ten skrypt ruby ​​jest następnie wywoływany z mojego skryptu bash (który mogę modyfikować). Kiedy używam powyższego, drukuje komunikaty o błędach w postaci zwykłego tekstu, pomijając formatowanie. Czy jest jakiś sposób, aby zachować formatowanie ekranowe i uzyskać wyjście (zarówno stdout, jak i stderr) również w pliku?
atlantis

8
Zauważ, że (domyślnie) ma to efekt uboczny, który $?nie odnosi się już do statusu wyjścia do_something, ale do statusu wyjścia tee.
Flimm,

255

Możesz przekierować stderr na stdout, a stdout do pliku:

some_command >file.log 2>&1 

Zobacz http://tldp.org/LDP/abs/html/io-redirection.html

Ten format jest preferowany niż najpopularniejszy &> format, który działa tylko w bash. W powłoce Bourne'a można to interpretować jako uruchamianie polecenia w tle. Również format jest bardziej czytelny 2 (jest STDERR) przekierowany na 1 (STDOUT).

EDYCJA: zmieniła kolejność, jak wskazano w komentarzach


47
To przekierowuje stderr do oryginalnego stdout, a nie do pliku, do którego zmierza stdout. Umieść „2> i 1” po „> file.log” i to działa.

1
Jaka jest zaleta tego podejścia w porównaniu z plikiem some_command &> file.log?
ubermonkey

6
Jeśli chcesz dołączyć do pliku, musisz to zrobić w ten sposób: echo „foo” 2> & 1 1 >> bar.txt AFAIK nie ma sposobu, aby dołączyć za pomocą &>
SlappyTheFish

9
Argh, przepraszam, echo „foo” 1 >> bar.txt 2> i 1
SlappyTheFish

11
Myślę, że interpretacja, że ​​2> i 1 przekierowuje stderr na stdout, jest błędna; Uważam, że dokładniej jest powiedzieć, że wysyła stderr w to samo miejsce, w którym aktualnie wybiera się stdout. Dlatego miejsce 2> i 1 po pierwszym przekierowaniu jest niezbędne.
jdg

201
# Close STDOUT file descriptor
exec 1<&-
# Close STDERR FD
exec 2<&-

# Open STDOUT as $LOG_FILE file for read and write.
exec 1<>$LOG_FILE

# Redirect STDERR to STDOUT
exec 2>&1

echo "This line will appear in $LOG_FILE, not 'on screen'"

Teraz proste echo zapisze się w $ LOG_FILE. Przydatny do demonizacji.

Do autora oryginalnego postu

To zależy od tego, co musisz osiągnąć. Jeśli musisz przekierować polecenie / polecenie z skryptu, odpowiedzi są już podane. Mój dotyczy przekierowania w ramach bieżącego skryptu, który wpływa na wszystkie polecenia / wbudowane (w tym widelce) po wspomnianym fragmencie kodu.


Innym fajnym rozwiązaniem jest przekierowanie zarówno do standardowego wyjścia / wyjścia ORAZ do programu rejestrującego lub pliku dziennika jednocześnie, co obejmuje podzielenie „strumienia” na dwa. Funkcję tę zapewnia komenda „tee”, która może zapisywać / dołączać jednocześnie do kilku deskryptorów plików (plików, gniazd, potoków itp.): Tee FILE1 FILE2 ...> (cmd1)> (cmd2) ...

exec 3>&1 4>&2 1> >(tee >(logger -i -t 'my_script_tag') >&3) 2> >(tee >(logger -i -t 'my_script_tag') >&4)
trap 'cleanup' INT QUIT TERM EXIT


get_pids_of_ppid() {
    local ppid="$1"

    RETVAL=''
    local pids=`ps x -o pid,ppid | awk "\\$2 == \\"$ppid\\" { print \\$1 }"`
    RETVAL="$pids"
}


# Needed to kill processes running in background
cleanup() {
    local current_pid element
    local pids=( "$$" )

    running_pids=("${pids[@]}")

    while :; do
        current_pid="${running_pids[0]}"
        [ -z "$current_pid" ] && break

        running_pids=("${running_pids[@]:1}")
        get_pids_of_ppid $current_pid
        local new_pids="$RETVAL"
        [ -z "$new_pids" ] && continue

        for element in $new_pids; do
            running_pids+=("$element")
            pids=("$element" "${pids[@]}")
        done
    done

    kill ${pids[@]} 2>/dev/null
}

Tak więc od samego początku. Załóżmy, że mamy terminal podłączony do / dev / stdout (FD # 1) i / dev / stderr (FD # 2). W praktyce może to być rura, gniazdo lub cokolwiek innego.

  • Utwórz FD 3 i 4 i wskaż tę samą „lokalizację”, co odpowiednio 1 i 2. Zmiana FD # 1 nie wpływa odtąd na FD # 3. Teraz FD 3 i 4 wskazują odpowiednio na STDOUT i STDERR. Będą one używane jako rzeczywisty terminal STDOUT i STDERR.
  • 1>> (...) przekierowuje STDOUT na polecenie w parens
  • parens (podpowłoka) wykonuje odczyt „tee” z STDOUT exec (potok) i przekierowuje do polecenia „logger” za pomocą innego potoku do podpowłoki w parens. Jednocześnie kopiuje to samo wejście do FD # 3 (terminal)
  • druga część, bardzo podobna, dotyczy wykonania tej samej sztuczki dla STDERR i FD # 2 i # 4.

Wynik uruchomienia skryptu o powyższej linii i dodatkowo tej:

echo "Will end up in STDOUT(terminal) and /var/log/messages"

...następująco:

$ ./my_script
Will end up in STDOUT(terminal) and /var/log/messages

$ tail -n1 /var/log/messages
Sep 23 15:54:03 wks056 my_script_tag[11644]: Will end up in STDOUT(terminal) and /var/log/messages

Jeśli chcesz zobaczyć wyraźniejszy obraz, dodaj te 2 wiersze do skryptu:

ls -l /proc/self/fd/
ps xf

1
tylko jeden wyjątek. w pierwszym przykładzie napisałeś: exec 1 <> $ LOG_FILE. powoduje to, że oryginalny plik dziennika jest zawsze własnością. dla prawdziwego logowania lepszy sposób to: exec 1 >> $ PLIK_LOGU, ponieważ dziennik jest zawsze dołączany.
Znik

4
To prawda, choć zależy to od intencji. Moje podejście polega na tym, aby zawsze tworzyć unikalny plik dziennika ze znacznikiem czasu. Drugim jest dołączenie. Oba sposoby można „logrotować”. Wolę osobne pliki, które wymagają mniejszego analizowania, ale jak powiedziałem, cokolwiek sprawia, że ​​twoja łódź pływa :)
quizac

1
Twoje drugie rozwiązanie ma charakter informacyjny, ale co z całym kodem czyszczenia? Nie wydaje się to istotne, a jeśli tak, to tylko zamazuje dobry przykład. Chciałbym również, aby został on nieco przerobiony, tak aby FD 1 i 2 nie były przekierowywane do programu rejestrującego, ale raczej 3 i 4, aby wszystko, co wywołuje ten skrypt, mogło manipulować 1 i 2 dalej przy wspólnym założeniu stdout == 1 i stderr == 2, ale moje krótkie eksperymenty sugerują, że jest to bardziej złożone.
JFlo

1
Bardziej podoba mi się to z kodem czyszczenia. Może to być trochę odwrócenie uwagi od podstawowego przykładu, ale usunięcie go spowoduje, że przykład będzie niekompletny. Sieć jest już pełna przykładów bez obsługi błędów lub przynajmniej przyjazną notatkę, że nadal potrzebuje około stu linii kodu, aby korzystanie z niej było bezpieczne.
Zoltan K.,

1
Chciałem rozwinąć kod czyszczenia. Jest to część skryptu, który demonizuje ergo, staje się odporny na sygnał HANG-UP. „tee” i „logger” są procesami spawnowanymi przez ten sam PPID i dziedziczą pułapkę HUP z głównego skryptu bash. Kiedy główny proces umiera, zostają odziedziczone przez init [1]. Nie staną się zombie (defunc). Kod czyszczenia zapewnia, że ​​wszystkie zadania w tle zostaną zabite, jeśli główny skrypt umrze. Dotyczy to również każdego innego procesu, który mógł zostać utworzony i działał w tle.
quiz z

41
bash your_script.sh 1>file.log 2>&1

1>file.loginstruuje powłokę, aby wysłała STDOUT do pliku file.logi 2>&1każe przekierować STDERR (deskryptor pliku 2) do STDOUT (deskryptor pliku 1).

Uwaga: kolejność ma znaczenie, jak wskazano liw.fi, 2>&1 1>file.lognie działa.


21

Co ciekawe, działa to:

yourcommand &> filename

Ale to powoduje błąd składniowy:

yourcommand &>> filename
syntax error near unexpected token `>'

Musisz użyć:

yourcommand 1>> filename 2>&1

10
&>>wydaje się działać na BASH 4:$ echo $BASH_VERSION 4.1.5(1)-release $ (echo to stdout; echo to stderr > /dev/stderr) &>> /dev/null
user272735

15

Krótka odpowiedź: Command >filename 2>&1lubCommand &>filename


Wyjaśnienie:

Rozważ następujący kod, który wypisuje słowo „stdout” na stdout, a słowo „stderror” na stderror.

$ (echo "stdout"; echo "stderror" >&2)
stdout
stderror

Zauważ, że operator „&” mówi bashowi, że 2 to deskryptor pliku (który wskazuje na stderr), a nie nazwa pliku. Jeśli pominiemy „&”, to polecenie wypisuje stdoutna standardowe wyjście, tworzy plik o nazwie „2” i stderrortam zapisuje .

Eksperymentując z powyższym kodem, możesz przekonać się dokładnie, jak działają operatory przekierowania. Na przykład, zmieniając plik, który z dwóch deskryptorów 1,2zostanie przekierowany do /dev/nullnastępujących dwóch wierszy kodu, usuń wszystko odpowiednio ze standardowego wyjścia, a wszystko odpowiednio ze standardowego błędu (wypisywanie pozostałych).

$ (echo "stdout"; echo "stderror" >&2) 1>/dev/null
stderror
$ (echo "stdout"; echo "stderror" >&2) 2>/dev/null
stdout

Teraz możemy wyjaśnić, dlaczego rozwiązanie, dlaczego poniższy kod nie generuje danych wyjściowych:

(echo "stdout"; echo "stderror" >&2) >/dev/null 2>&1

Aby naprawdę to zrozumieć, zdecydowanie zalecamy przeczytanie tej strony w tabelach deskryptorów plików . Zakładając, że zrobiłeś to czytanie, możemy kontynuować. Zauważ, że Bash przetwarza od lewej do prawej; w ten sposób Bash widzi >/dev/nullpierwszy (który jest taki sam jak 1>/dev/null) i ustawia deskryptor pliku 1 tak, aby wskazywał / dev / null zamiast standardowego wyjścia. Po zrobieniu tego Bash następnie porusza się w prawo i widzi 2>&1. Ustawia to deskryptor pliku 2 tak, aby wskazywał na ten sam plik co deskryptor pliku 1 (a nie na sam deskryptor pliku 1 !!!! (zobacz ten zasób na temat wskaźnikówpo więcej informacji)) . Ponieważ deskryptor pliku 1 wskazuje na / dev / null, a deskryptor pliku 2 wskazuje na ten sam plik co deskryptor pliku 1, deskryptor pliku 2 teraz wskazuje również na / dev / null. Zatem oba deskryptory plików wskazują na / dev / null, i dlatego żadne wyjście nie jest renderowane.


Aby sprawdzić, czy naprawdę rozumiesz pojęcie, spróbuj zgadnąć dane wyjściowe, gdy zmienimy kolejność przekierowań:

(echo "stdout"; echo "stderror" >&2)  2>&1 >/dev/null

stderror

Powodem jest to, że oceniając od lewej do prawej, Bash widzi 2> i 1, a tym samym ustawia deskryptor pliku 2 tak, aby wskazywał to samo miejsce, co deskryptor pliku 1, tj. Stdout. Następnie ustawia deskryptor pliku 1 (pamiętaj, że> / dev / null = 1> / dev / null) wskazuje na> / dev / null, usuwając w ten sposób wszystko, co zwykle byłoby wysyłane do standardowego wyjścia. Zatem pozostaje nam tylko to, co nie zostało wysłane do standardowego wyjścia w podpowłoce (kod w nawiasach) - tzn. „Stderror”. Interesującą rzeczą do odnotowania jest to, że chociaż 1 jest tylko wskaźnikiem do standardowego wyjścia, przekierowanie wskaźnika 2 na 1 przez2>&1 NIE tworzy łańcucha wskaźników 2 -> 1 -> standardowego. Jeśli tak, w wyniku przekierowania 1 do / dev / null, kod2>&1 >/dev/null dałby łańcuch wskaźnika 2 -> 1 -> / dev / null, a zatem kod nie wygenerowałby nic, w przeciwieństwie do tego, co widzieliśmy powyżej.


Na koniec zauważę, że istnieje prostszy sposób:

W sekcji 3.6.4 tutaj widzimy, że możemy użyć operatora &>do przekierowania zarówno stdout, jak i stderr. Tak więc, aby przekierować zarówno wyjście stderr, jak i wyjście standardowe na dowolne polecenie \dev\null(które usuwa dane wyjściowe), po prostu wpiszemy $ command &> /dev/null lub w przypadku mojego przykładu:

$ (echo "stdout"; echo "stderror" >&2) &>/dev/null

Najważniejsze dania na wynos:

  • Deskryptory plików zachowują się jak wskaźniki (chociaż deskryptory plików nie są takie same jak wskaźniki plików)
  • Przekierowanie deskryptora pliku „a” do deskryptora pliku „b”, który wskazuje na plik „f”, powoduje, że deskryptor pliku „a” wskazuje to samo miejsce, co deskryptor pliku b - plik „f”. NIE tworzy łańcucha wskaźników a -> b -> f
  • Z tego powodu kolejność ma znaczenie, 2>&1 >/dev/nulljest! = >/dev/null 2>&1. Jedno generuje wyjście, a drugie nie!

Na koniec spójrz na te wspaniałe zasoby:

Dokumentacja Bash na temat przekierowań , objaśnienie tabel deskryptorów plików , wprowadzenie do wskaźników


Deskryptory plików (0, 1, 2) są po prostu przesunięciami do tabeli. Gdy używane są 2> i 1, efektem jest szczelina FD [2] = dup (1), więc gdziekolwiek FD [1] wskazywał FD [2], teraz wskazuje. Kiedy zmienisz FD [1], aby wskazywał na / dev / null, wtedy FD [1] ulega zmianie, ale nie zmienia to gniazda FD [2] (który wskazuje na standardowe wyjście). Używam terminu dup (), ponieważ jest to wywołanie systemowe używane do kopiowania deskryptora pliku.
PatS

11
LOG_FACILITY="local7.notice"
LOG_TOPIC="my-prog-name"
LOG_TOPIC_OUT="$LOG_TOPIC-out[$$]"
LOG_TOPIC_ERR="$LOG_TOPIC-err[$$]"

exec 3>&1 > >(tee -a /dev/fd/3 | logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_OUT" )
exec 2> >(logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_ERR" )

Jest to powiązane: Pisanie stdOut i stderr do syslog.

To prawie działa, ale nie z Xinted; (


Zgaduję, że to nie działa z powodu „/ dev / fd / 3 Odmowa dostępu”. Zmiana na> i 3 może pomóc.
quizac

6

Chciałem, aby rozwiązaniem było zapisanie danych wyjściowych ze stdout plus stderr w pliku dziennika, a stderr wciąż na konsoli. Więc musiałem zduplikować wyjście stderr przez tee.

Oto rozwiązanie, które znalazłem:

command 3>&1 1>&2 2>&3 1>>logfile | tee -a logfile
  • Najpierw zamień stderr i stdout
  • następnie dołącz stdout do pliku dziennika
  • potoku rury do trójnika i dołączyć go również do pliku dziennika

BTW, to nie działało dla mnie (plik dziennika jest pusty). | tee nie ma wpływu. Zamiast tego uruchomiłem go za pomocą stackoverflow.com/questions/692000/…
Jarosław Bułatow

4

W sytuacji, gdy konieczne jest „orurowanie”, możesz użyć:

| I

Na przykład:

echo -ne "15\n100\n"|sort -c |& tee >sort_result.txt

lub

TIMEFORMAT=%R;for i in `seq 1 20` ; do time kubectl get pods |grep node >>js.log  ; done |& sort -h

Te rozwiązania bazujące na bash mogą przesyłać STDOUT i STDERR osobno (od STDERR „sort -c” lub od STDERR do „sort-h”).


1

„Najprostszym” sposób (tylko bash4) ls * 2>&- 1>&-.


1

Poniższych funkcji można użyć do zautomatyzowania procesu przełączania wyjść między stdout / stderr i plikiem dziennika.

#!/bin/bash

    #set -x

    # global vars
    OUTPUTS_REDIRECTED="false"
    LOGFILE=/dev/stdout

    # "private" function used by redirect_outputs_to_logfile()
    function save_standard_outputs {
        if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot save standard outputs because they have been redirected before"
            exit 1;
        fi
        exec 3>&1
        exec 4>&2

        trap restore_standard_outputs EXIT
    }

    # Params: $1 => logfile to write to
    function redirect_outputs_to_logfile {
        if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot redirect standard outputs because they have been redirected before"
            exit 1;
        fi
        LOGFILE=$1
        if [ -z "$LOGFILE" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: logfile empty [$LOGFILE]"

        fi
        if [ ! -f $LOGFILE ]; then
            touch $LOGFILE
        fi
        if [ ! -f $LOGFILE ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: creating logfile [$LOGFILE]"
            exit 1
        fi

        save_standard_outputs

        exec 1>>${LOGFILE%.log}.log
        exec 2>&1
        OUTPUTS_REDIRECTED="true"
    }

    # "private" function used by save_standard_outputs() 
    function restore_standard_outputs {
        if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot restore standard outputs because they have NOT been redirected"
            exit 1;
        fi
        exec 1>&-   #closes FD 1 (logfile)
        exec 2>&-   #closes FD 2 (logfile)
        exec 2>&4   #restore stderr
        exec 1>&3   #restore stdout

        OUTPUTS_REDIRECTED="false"
    }

Przykład użycia w skrypcie:

echo "this goes to stdout"
redirect_outputs_to_logfile /tmp/one.log
echo "this goes to logfile"
restore_standard_outputs 
echo "this goes to stdout"

kiedy używam twoich funkcji i próbuje przywrócić standardowe dane wyjściowe, pojawia się echo: błąd zapisu: zły numer pliku przekierowanie działa idealnie ... przywracanie nie wydaje się
thom schumacher

aby skrypt mógł działać, musiałem skomentować te wiersze i zmieniłem kolejność: #exec 1> & - #closes FD 1 (plik dziennika) #exec 2> & - #closes FD 2 (plik dziennika); exec 1> i 3 #restore stdout exec 2> & 4
#restore

Przykro mi to słyszeć. Nie otrzymuję żadnych błędów podczas uruchamiania w CentOS 7, bash 4.2.46. Zanotowałem odniesienie, w którym otrzymałem te polecenia. Jest: Ref: logan.tw/posts/2016/02/20/open-and-close-files-in-bash
Fernando Fabreti

Korzystam z tych poleceń w systemie AIX i prawdopodobnie dlatego. Dodałem post dotyczący poprawki, którą zrobiłem.
thom schumacher

1

@ fernando-fabreti

Dodając do tego, co zrobiłeś, nieznacznie zmieniłem funkcje i usunąłem & - zamknięcie i zadziałało to dla mnie.

    function saveStandardOutputs {
      if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
        exec 3>&1
        exec 4>&2
        trap restoreStandardOutputs EXIT
      else
          echo "[ERROR]: ${FUNCNAME[0]}: Cannot save standard outputs because they have been redirected before"
          exit 1;
      fi
  }

  # Params: $1 => logfile to write to
  function redirectOutputsToLogfile {
      if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
        LOGFILE=$1
        if [ -z "$LOGFILE" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: logfile empty [$LOGFILE]"
        fi
        if [ ! -f $LOGFILE ]; then
            touch $LOGFILE
        fi
        if [ ! -f $LOGFILE ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: creating logfile [$LOGFILE]"
            exit 1
        fi
        saveStandardOutputs
        exec 1>>${LOGFILE}
        exec 2>&1
        OUTPUTS_REDIRECTED="true"
      else
        echo "[ERROR]: ${FUNCNAME[0]}: Cannot redirect standard outputs because they have been redirected before"
          exit 1;
      fi
  }
  function restoreStandardOutputs {
      if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
      exec 1>&3   #restore stdout
      exec 2>&4   #restore stderr
      OUTPUTS_REDIRECTED="false"
     fi
  }
  LOGFILE_NAME="tmp/one.log"
  OUTPUTS_REDIRECTED="false"

  echo "this goes to stdout"
  redirectOutputsToLogfile $LOGFILE_NAME
  echo "this goes to logfile"
  echo "${LOGFILE_NAME}"
  restoreStandardOutputs 
  echo "After restore this goes to stdout"

1

W sytuacjach, gdy rozważasz użycie takich rzeczy exec 2>&1, łatwiej jest odczytać, jeśli to możliwe, przepisywanie kodu za pomocą funkcji bash takich jak to:

function myfunc(){
  [...]
}

myfunc &>mylog.log

0

W przypadku tcsh muszę użyć następującego polecenia:

command >& file

Jeśli zostanie użyty command &> file, pojawi się błąd „Niepoprawne polecenie zerowe”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.