Не могу выйти и странный порядок исполнения с тройником - PullRequest
0 голосов
/ 16 октября 2018

Я получаю странное поведение при передаче вывода функции в команду tee.Первая проблема заключается в том, что я не могу выйти из программы при использовании команды exit при вызове из функции, переданной по каналу tee.Например:

myfunction(){
    # Some stuff here
    exit 1
}

myfunction | tee -a $UPGRADE_LOG

Когда я запускаю приведенный выше код, программа не может завершиться и запускается до завершения.

Другая проблема, с которой я сталкиваюсь, заключается в том, что tee, кажется, имеет причинунекоторый код для запуска таким образом, что последовательный порядок отменяется.У меня есть следующий вывод:

SHOWING SYSTEM-WIDE AND INSTATNCE MEMORY USAGE:
Are you sure you would like to back up the instance given current memory contraints? [y/n]: Filesystem                           Size   Used  Avail  Use%  Mounted on
/dev/mapper/system-root              15G    13G   1.5G   90%   /
Log File Size: 24K   Total Size to Package: 248K Available Space: 1.5G

Когда он должен работать как:

SHOWING SYSTEM-WIDE AND INSTATNCE MEMORY USAGE:
Filesystem                           Size   Used  Avail  Use%  Mounted on
/dev/mapper/system-root              15G    13G   1.5G   90%   /
Log File Size: 24K   Total Size to Package: 248K Available Space: 1.5G
Are you sure you would like to back up the instance given current memory contraints? [y/n]: 

Все работает правильно, когда не используется tee.Проблемы, кажется, связаны друг с другом.Есть идеи, почему это так и что мне с этим делать?

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Ответ Квантура говорит вам, почему это происходит.Этот говорит вам, как это исправить.:)

with_logs_piped() {
  local logfile=$1; shift
  "$@" > >(tee -a -- "$logfile") 2>&1  # 2>&1 redirects stderr through the same tee so it's
}                                      # ...also logged, and shows up sync'd with stdout.

myfunction() {
    # Some stuff here
    exit 1
}

with_logs_piped "$UPGRADE_LOG" myfunction

Здесь важно то, что вместо обычного конвейера мы используем замену процесса для tee - поэтому myfunction запускается в вашей оболочкесам по себе, а не подоболочка, поэтому exit применяется правильно.


Что касается того, почему перенаправление stdout через tee десинхронизирует stderr, см. Отдельное перенаправление и рекомбинация stderr / stdout без потери порядка

0 голосов
/ 16 октября 2018

Оператор exit выходит из (под-) оболочки, в которой выполняется процесс. Теперь наступает сюрприз:

Трубопроводы

Aконвейер представляет собой последовательность из одной или нескольких команд, разделенных одним из управляющих операторов | или |&.Формат для конвейера:

[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]

Каждая команда в конвейере выполняется как отдельный процесс (т. Е. В подоболочке).

source: man bash

Таким образом, оператор exit из функции просто убивает подоболочку конвейера.На самом деле это означает, что exit ничего не делает в конвейере

$ exit | exit | echo foo
foo
$ exit | exit
$ # shell not terminated

Примечание: это явно зависит от оболочки, потому что ведет себя по-разному.

...