Скопируйте stdout и stderr к файлу журнала и оставьте их на консоли в рамках самого сценария

tar надежная, файловая система только добавления, которая является подходящей к архивации. Можно записать сырые данные в tar от UNIX, таким образом:

tar cf -b $BLOCKSIZE /dev/hda ~

или из Windows можно создать/извлечь файлы tar с помощью очень способного Winzip, но это оставляет Вас с проблемой необработанного чтения-записи dev доступом из Windows. Начиная с Windows Server 2003 это было хитро, чтобы сделать, но код из проекта DiskSector (непротестированный!) выглядит многообещающим. Я оставляю это как проект для себя упаковать это в удобные сценарии...

8
12.03.2013, 17:40
4 ответа

Вы ищете tee.

Посмотрите man tee для деталей.

Объединить его с exec, необходимо использовать замену процесса. (См. man bash для деталей.)

exec &> >(tee  log.out)
echo "This is stdout"
echo "This is stderr" >&2
8
27.01.2020, 20:09
  • 1
    я посмотрел на него. Выполнение exec 2>&1 | tee -a log.out только печать на консоли, ничем в файле журнала. Возможно, я не использую правильный синтаксис? –  adarshr 12.03.2013, 13:58
  • 2
    @adarshr перепроверьте свой код. Я записал о tee в сочетании с заменой процесса. –  H.-Dirk Schmitt 12.03.2013, 14:34
  • 3
    Это объединяет stdout и stderr, хотя и может иметь тот же вид побочного эффекта, как упомянуто в моем ответе. примечание –  Stéphane Chazelas 12.03.2013, 15:05
  • 4
    @StephaneChazelas на пример кода в вопросе - который был намерением от OP. –  H.-Dirk Schmitt 12.03.2013, 15:46
  • 5
    То, что я подразумеваю под слиянием, - то, что теперь ошибки сценария переходят к stdout. Таким образом, если кто-то делает the-script | wc -l например, это будет также считать ошибочные строки, и Вы не будете видеть ошибок. –  Stéphane Chazelas 12.03.2013, 16:18

Можно сделать:

: > log # empty log file if necessary
{ { {

  ...the script

} 3>&- | tee -a log >&3 3>&-
exit "${PIPESTATUS[0]}"
} 2>&1 | tee -a log >&2 3>&-
} 3>&1
exit "${PIPESTATUS[0]}"

Вы могли также записать это как:

: > log # empty log file if necessary
exec 2> >(tee -a log >&2) > >(tee -a log)

...the script

Но потому что удар не ожидает тех процессов, запущенных с >(...), это имеет противный эффект иногда вывода чего-то к терминалу после того, как команда возвратилась, который может иметь еще более противные эффекты (как тихое отбрасывание, которые производят), если терминал "tostop" атрибут работает.

В любом случае, путем создания stdout канал в обоих решениях, и потому что две команды независимо производят выходные сигналы и сообщения об ошибках, это будет влиять на выходную буферизацию и порядок, выходные сигналы и сообщения об ошибках отображены.

4
27.01.2020, 20:09
  • 1
    я думаю Ваша вторая мишень, пропускает перенаправление к stderr. Это должно быть: tee -a log >&2 3>&- –  richvdh 04.12.2014, 14:26

Обычно возможности наследуются нижестоящим элементам. Как указано в manpage :

Нижестоящий элемент, созданный с помощью вилки (2), наследует копии родительских наборов возможностей.

Проблема скриптов заключается в том, что они не являются непосредственно исполняемыми. Ядро проходит через список проверок (код ядра находится в fs/binfmt_*.c). Один из них - «binfmt_script.c,», который проверяет первую строку на шебанг, затем вызывает реальный интерпретатор (тот, что в шебанге) с вашим сценарием в качестве аргумента. Поэтому вызывается стандартный/общий интерпретатор, который просто считывает сценарий в качестве аргумента.

Это означает, что вам придется установить возможность на интерпретаторе, а не на сценарии. То же самое относится к suid битам и другим специальным флагам.

Поэтому либо вы делаете копию вашего интерпретатора, устанавливаете на нем нужные возможности (также проверьте, что никто не может получить к нему доступ через chmod/chown), и вызываете этот скопированный интерпретатор в своем шебанге. Можно также использовать логику setcap в сценарии.

-121--31474-

Будут распечатаны имена разорванных symlinks в текущем каталоге.

for l in $(find . -type l); do cd $(dirname $l); if [ ! -e "$(readlink $(basename $l))" ]; then echo $l; fi; cd - > /dev/null; done

Работает в Баше. Не знаю о других снарядах.

-121--159-

Еще один способ сделать это - использовать перенаправления внутри функций.

#!/bin/bash

function1 () {
    echo 'STDOUT from function 1'
    echo 'STDERR from function 1' >&2
}

function2 () {
    echo 'STDOUT from function 2'
    echo 'STDERR from function 2' >&2
}


function3 () {
    echo 'STDOUT from function 3'
    echo 'STDERR from function 3' >&2
}

main() {
    function1
    function2
    function3
}

main 2>&1 |tee log.txt

Здесь имеется основная функция, которая вызывает все остальные функции. Перенаправление STDOUT и STDERR основной функции на тройник .

1
27.01.2020, 20:09

Я знаю, что это старый пост, но почему бы просто не сделать это?

echo "hi" >> log.txt #stdout -> log
echo "hi" | tee -a log.txt #stdout -> log & stdout
echo "hi" &>> log.txt #stdout & stderr -> log
echo "hi" |& tee -a log.txt #stdout & stderr -> log & stdout

И, конечно же, если вам нужен стандартный вывод, вы можете просто регулярно печатать.

Вы можете сделать это с любой комбинацией потоков, просто используя эти две основные команды.

Я знаю, что я пришел сюда и не получил простой для понимания/реализовать ответ, надеюсь, это поможет кому-то еще, кто борется.

Между прочим, для нубов, таких как мой предыдущий я, все, что делает команда tee, это выводит ввод stdin как на stdout, так и в файл (s ), указанный в качестве последующих аргументов. -aозначает добавление, поэтому вы не перезаписываете файл при каждом использовании команды. Если у вас есть дополнительные вопросы, я считаю этот очень полезным ресурсом для быстрого изучения bash.

6
27.01.2020, 20:09

Теги

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