Назад | Перейти на главную страницу

временно перенаправить STDOUT на другой файловый дескриптор, но по-прежнему на экран

Я делаю сценарий, который выполняет некоторые команды внутри, и эти команды показывают некоторый вывод на STDOUTSTDERR тоже, но это не проблема). Мне нужно, чтобы мой скрипт генерировал файл .tar.gz для STDOUT, поэтому вывод некоторых команд, выполняемых в скрипте, также попадает в STDOUT и это заканчивается недопустимым файлом .tar.gz на выходе.

Короче говоря, можно выводить первые команды на экран (так как я все еще хочу видеть вывод), но не через STDOUT? Также хотелось бы сохранить STDERR нетронутыми, поэтому там появляются только сообщения об ошибках.

Простой пример того, что я имею в виду. Это был бы мой сценарий:

#!/bin/bash

# the output of these commands shouldn't go to STDOUT, but still appear on screen
some_cmd foo bar
other_cmd baz

#the following command creates a tar.gz of the "whatever" folder,
#and outputs the result to STDOUT
tar zc whatever/

Я пробовал возиться с exec и дескрипторы файлов, но я все еще не могу заставить их работать:

#!/bin/bash

# save STDOUT to #3
exec 3>&1

# the output of these commands should go to #3 and screen, but not STDOUT
some_cmd foo bar
other_cmd baz

# restore STDOUT
exec 1>&3

# the output of this command should be the only one that goes to STDOUT
tar zc whatever/

Я думаю, мне не хватает закрытия STDOUT после первого exec и снова открыть его снова или что-то в этом роде, но я не могу найти правильный способ сделать это (прямо сейчас результат такой же, как если бы я не добавил execs

stdout - это экран. Между stdout и «экраном» нет разделения.

В этом случае я бы просто временно перенаправил stdout на stderr с помощью 1>&2 внутри подоболочки. Это приведет к тому, что вывод команд будет отображаться на экране, но не будет в потоке stdout программ.

#!/bin/bash

# the output of these commands shouldn't go to STDOUT, but still appear on screen

# Start a subshell
(
    1>&2                # Redirect stdout to stderr
    some_cmd foo bar
    other_cmd baz
)
# At the end of the subshell, the file descriptors are 
# as they usually are (no redirection) as the subshell has exited.

#the following command creates a tar.gz of the "whatever" folder,
#and outputs the result to STDOUT
tar zc whatever/

Есть ли причина, по которой вам нужно направить вывод этого скрипта во что-то еще? Обычно tar записывает в файл с помощью -f флаг или выполнить перенаправление только для команды tar: tar zc whatever > filename.tar.gz (если вы не помещали его на такое устройство, как магнитная лента, или не использовали его в качестве копии).

Было бы намного проще, если бы вы использовали -f переключиться на команду tar, чтобы указать tar, что нужно писать в файл?

tar zcf whatever.tar.gz whatever/

Если это не дает того, что вы хотите, вам придется перенаправлять индивидуально каждую команду, которая может писать в STDOUT.

some_cmd foo bar 1>&2

Думаю, вы ищете какое-то мультиплексирование.

Это простой пример того, как добавить метку времени к каждой строке стандартного вывода: http://www.podciborski.co.uk/programming/perl/add-a-timestamp-to-every-stdout-line/

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

ssh user@remoteserver the_script.sh | create_tar.sh filename

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