Трубить bash stdout только в режиме отладки

Я пытаюсь добиться этого:

PIPE=""
if [ $DEBUG = "true" ]; then
    PIPE="2> /dev/null"
fi
git submodule init $PIPE

Но $PIPEgets интерпретируется как аргументы командной строки для git. Как показать stdout и stderr только в режиме отладки, а в режиме без отладки передать только stderr?


Спасибо за отличные идеи. В итоге сделал это, что перенаправляет все на /dev/null, если не в режиме отладки, и печатает как stderr, так и stdout в режиме отладки:

# debug mode
if [[ ${DEBUG} = true ]]; then
    PIPE=/dev/stdout
else
    PIPE=/dev/null
fi

git submodule init 2>"${PIPE}" 1>"${PIPE}"

person knutole    schedule 29.05.2017    source источник
comment
Вы пробовали поставить $PIPE обратными кавычками? `$ ТРУБА`   -  person aardvarkk    schedule 29.05.2017
comment
Спасибо, но это не работает, все еще получаю line 17: 2>: command not found   -  person knutole    schedule 29.05.2017
comment
Какую версию Баша вы используете? Ваш исходный код, кажется, отлично работает на моей версии Mac 3.2.57(1)-release   -  person aardvarkk    schedule 29.05.2017
comment
И вы пытались запустить только этот код выше, и вы получили эту ошибку? Я в основном скопировал и вставил ваш код и добавил одну строку, говорящую $DEBUG="true", и я не получил никаких ошибок о том, что команда не найдена...   -  person aardvarkk    schedule 29.05.2017
comment
Странно, я получаю fatal: /dev/null: '/dev/null' is outside repository, когда PIPE="> /dev/null" и работаю git submodule init $PIPE   -  person knutole    schedule 29.05.2017
comment
Вы пробовали git submodule init `eval $PIPE`   -  person aardvarkk    schedule 29.05.2017


Ответы (2)


Использование переменной после >

if [[ ${DEBUG} = true ]]; then
    errfile=/dev/stderr
else
    errfile=/dev/null
fi

command 2>"${errfile}"

Изменение файловых дескрипторов

Вы можете продублировать stderr в новый файловый дескриптор 3.

if [[ ${DEBUG} = true ]]; then
    exec 3>&2
else
    exec 3>/dev/null
fi

затем для каждой команды вы хотите использовать новое перенаправление

command 2>&3

Чтобы закрыть fd 3, если он больше не нужен

exec 3>&-
person Nahuel Fouilleul    schedule 29.05.2017
comment
Спасибо, но вопрос в том, как использовать переменную $PIPE, если это возможно. - person knutole; 29.05.2017
comment
невозможно использовать перенаправление '›' внутри переменной, потому что перенаправление выполняется до раскрытия переменной, но вы можете использовать переменную после знака > - person Nahuel Fouilleul; 29.05.2017
comment
Итак, 2› перенаправляет stderr, но как перенаправить таким образом и stderr, и stdout? 2>&1>/dev/null ? - person knutole; 29.05.2017
comment
Кстати, это тоже сработает... if [ "$DEBUG" != "true" ]; then exec 2> /dev/null; fi Вы также можете закоротить его с помощью [ "$DEBUG" == "true" ] || exec 2> /dev/null - person anishsane; 30.05.2017
comment
Да, на самом деле это была моя основная идея, но я немного устал. exec 3›&2 для резервного копирования fd2, затем exec 2›/dev/null и, наконец, после команд exec 2›&3 3›&- для восстановления fd2 и закрытия fd3, но в зависимости от использования пользователем, я хотя он мог использовать команды с обычным fd2 между git-командами - person Nahuel Fouilleul; 30.05.2017
comment
Следует отметить, что мы также можем использовать подоболочку и перенаправить fd1 и fd2 один раз. - person Nahuel Fouilleul; 30.05.2017

Во-первых, я предполагаю, что ваша логика работает неправильно, с DEBUG=true вы будете отправлять stderr в /dev/null. Кроме того, в вашем сравнении строк отсутствует второй "=",

Как насчет простого решения?

if [ "${DEBUG}" == "true" ]; then
    git submodule init
else
    git submodule init  2>/dev/null
fi

Изменить после вашего ответа:

В качестве альтернативы вы можете использовать eval, но будьте осторожны, это считается злом;)

if [ "${DEBUG}" == "true" ]; then
    PIPE=""
else
    PIPE="2>/dev/null" 
fi 
eval git submodule init $PIPE
person olisch    schedule 29.05.2017
comment
Да, спасибо за это, но у меня длинный список функций, поэтому я хотел бы иметь $PIPE. - person knutole; 29.05.2017