Различие между 2> &1> output.log и 2> &1 | кладет для первого удара output.log

Вот другое решение C, для которого только нужны STD C и меньше памяти:

#include <stdio.h>

int main(int argc, char **argv)
{
  if (argc < 2 || !*argv[1]) {
    puts("Argument missing.");
    return 1;
  }
  char c = *argv[1], x = 0;
  size_t count = 0;
  while ((x = getc(stdin)) != EOF)
    if (x == '\n') {
      printf("%zd\n", count);
      count = 0;
    } else if (x == c)
      ++count;
  return 0;
}
36
11.09.2011, 02:06
7 ответов

Рассмотрение двух команд по отдельности:

utility 2>&1 >output.log 

Здесь, поскольку перенаправления обрабатываются слева -на -справа, стандартный поток ошибок сначала будет перенаправлен туда, куда направляется стандартный поток вывода (, возможно, на консоль ), а затем стандартный поток вывода будет перенаправлен в файл. Стандартный поток ошибок , а не будет перенаправлен в этот файл.

Видимым эффектом этого будет то, что вы получите результат стандартной ошибки на экране и результат стандартного вывода в файле.

utility 2>&1 | tee output.log

Здесь вы перенаправляете стандартную ошибку в то же место, что и стандартный поток вывода. Это означает, что оба потока будут переданы утилите teeкак один смешанный выходной поток, и что эти стандартные выходные данные будут сохранены в указанный файл с помощью tee. Данные будут дополнительно воспроизводиться teeв консоли (вот что делает tee, дублирует потоки данных ).

Какой из них используется, зависит от того, чего вы хотите достичь.

Обратите внимание, что вы не сможете воспроизвести эффект второго конвейера только с помощью >(, как в utility >output.log 2>&1, который сохранил бы и стандартный вывод, и ошибку в файле, сначала перенаправляя стандартный вывод на output.log. файл, а затем перенаправить стандартную ошибку туда, куда теперь идет стандартный вывод ). Вам нужно будет использовать teeдля получения данных в консоли, а также в выходном файле.


Дополнительные примечания:

видимый эффект первой команды,

utility 2>&1 >output.log 

будет таким же, как

utility >output.log

Т. е. стандартный вывод идет в файл, а стандартная ошибка — в консоль.

Если бы в конце каждой из приведенных выше команд был добавлен дополнительный шаг обработки, была бы большая разница:

utility 2>&1 >output.log | more_stuff

utility >output.log      | more_stuff

В первом конвейере more_stuffполучит исходный стандартный поток ошибок из utilityв качестве своих стандартных входных данных, а во втором конвейере, поскольку только результирующий стандартный поток вывода когда-либо отправляется по каналу., часть more_stuffконвейера не получит ничего для чтения на своем стандартном вводе.

30
27.01.2020, 19:36

Редакционная статья

Удостоверьтесь, что прочитали комментарии к этому ответуderobert.


Исходный ответ

2>&1 >output.log средства сначала начинают отправлять, весь материал дескриптора файла 2 (стандартная погрешность) к дескриптору файла 1 (стандартный вывод) затем отправляют это в файл output.log. Другими словами, отправьте стандартную погрешность и стандартный вывод к файлу журнала.

2>&1 | tee output.log то же с 2>&1 бит, это комбинирует стандартный вывод и стандартную погрешность на потоке стандартного вывода. Это затем передает это по каналу через tee программа, которая отправит ее стандартный вход в ее стандартный вывод (как cat) и также в файл. Таким образом, это комбинирует эти два потока (ошибка и вывод), затем выводы это к терминалу и файлу.

Нижняя строка - то, что первое отправляет stderr/stdout в файл, в то время как второе отправляет его и в файл и в стандартный вывод (который является, вероятно, терминалом, если Вы не в другой конструкции, которая перенаправила стандартный вывод).

Я упоминаю, что последняя возможность, потому что у Вас может быть материал как:

(echo hello | tee xyzzy.txt) >plugh.txt

где ничто не заканчивается на терминале.

24
27.01.2020, 19:36
  • 1
    1 Вы имеете право синтаксиса, но не семантику. Выполненный cat /doesnotexist 2>&1 >output.txt - Вы будете видеть, посмотрите cat: /doesnotexist: No such file or directory отображенный к терминалу и output.txt пустой файл. Порядок очередности и закрытие находятся в игре: 2>&1 (копируйте fd2 от текущего fd1), затем >output.txt (перенаправьте fd1 к output.txt, не изменив ничто больше). Причина это 2>&1 | отличается, из-за порядка очередности: | прежде >. –  Arcege 11.09.2011, 02:33

Первая команда сделает другую задачу:

После

2>&1 > output.log 

старый STDOUT будет сохранен (скопированный) в STDERR, и затем STDOUT будет перенаправлен в файл.

Так, stdout перейдет к файлу, и stderr перейдет к консоли.

И в

 2>&1 | tee output.log

оба потока будут перенаправлены для кладения для первого удара. Мишень копирует любой вход к своему stdout (консоль в Вашем случае) и зарегистрировать (output.log).

И существует другая форма сначала:

    > output.log  2>&1

это перенаправит и STDOUT и STDERR в файл.

8
27.01.2020, 19:36

Бывшие выводы только в файл. Вторые выводы и в файл и на экран.

4
27.01.2020, 19:36

Причина 2>&1 | tee должен смочь получить и stdout и stderr к файлу журнала и видеть его на экране одновременно. Это могло быть сделано как >output.txt 2>&1 & tail -f также, но Вы не знали бы, когда фоновая завершенная команда - является завершенной программой или является ею работающий без вывода. 2>&1 | tee была общая идиома для программистов.

4
27.01.2020, 19:36

Вот пост суммировал выходные потоки Unix: http://www.devcodenote.com/2015/04/unix-outt-streams.html

фрагмент с поста:

Есть 3 Стандартные выходные потоки:

STDIN - Standard Input - Writes from an input device to the program
STDOUT - Standard Output - Writes program output to screen unless specified otherwise.
STDERR - Standard Error Output - Writes error messages. Also printed to the screen unless specified otherwise.
-1
27.01.2020, 19:36

Давайте сначала посмотрим на пример кода:

#include <stdio.h>
main() 
{
// message 1, on stdout (using  printf)
printf("%s",          "message 1, on stdout (using  printf)\n");

// message 2, on stdout (using fprintf)
fprintf(stdout, "%s", "message 2, on stdout (using fprintf)\n");

// message 3, on stderr (using fprintf)
fprintf(stderr, "%s", "message 3, on stderr (using fprintf)\n");
}

Сравним результаты:
./helloerror
+ файл :нет сообщения; консоль :сообщение 1,2,3;

./helloerror >error.txt
+ файл :сообщение 1,2; консоль :сообщение 3;

./helloerror 2>&1 >error.txt
+ файл :сообщение 1,2; консоль :сообщение 3;
+ то же, что и./helloerror >error.txt

./helloerror >error.txt 2>&1
+ файл :сообщение 3,1,2; консоль :нет сообщения;
+ обратите внимание, что сначала идет 3, затем 1, затем 2

./helloerror | tee error.txt 2>&1
+ файл :сообщение 1,2; консоль :сообщение 3,1,2;
+ обратите внимание, что сначала идет 3, затем 1, затем 2

./helloerror 2>&1 | tee error.txt
+ файл :сообщение 3,1,2; консоль :сообщение 3,1,2;

Для использования:
./helloerror >error.txt 2>&1
-> если нужно, чтобы все (сообщения stdout+stderr )были в файле, но не выводились на консоль

./helloerror 2>&1 | tee error.txt
-> если нужно, чтобы все сообщения (stdout+stderr )были в файле и выводились на консоль

0
27.01.2020, 19:36

Теги

Похожие вопросы