Я делаю сценарий, который выполняет некоторые команды внутри, и эти команды показывают некоторый вывод на STDOUT
(и STDERR
тоже, но это не проблема). Мне нужно, чтобы мой скрипт генерировал файл .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 и снова открыть его снова или что-то в этом роде, но я не могу найти правильный способ сделать это (прямо сейчас результат такой же, как если бы я не добавил exec
s
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 должен быть скриптом, который печатает строки с тегом журнала и перенаправляет другие строки в файл.