Перенаправить stderr на stdout в оболочке C

Когда я запускаю следующую команду в csh, я ничего не получаю, но она работает в bash. Есть ли эквивалент в csh, который может перенаправить стандартную ошибку на стандартный вывод?

somecommand 2>&1

person zdd    schedule 05.12.2012    source источник
comment
КШ опасен. Попробуйте перейти на bash, zsh faqs.org/faqs/unix- часто задаваемые вопросы/оболочка/csh-whynot   -  person SS Hegde    schedule 05.12.2012
comment
@SSHegde, что ты имеешь в виду под опасным?   -  person Géza Török    schedule 16.02.2017
comment
@Geza: Пожалуйста, перейдите по ссылке, которую я упомянул в комментарии. Это объясняет почему.   -  person SS Hegde    schedule 16.02.2017
comment
@SSHegde Хотел бы я отметить вашу ссылку на «csh-whynot»   -  person Trevor Boyd Smith    schedule 26.05.2017


Ответы (6)


Оболочка csh никогда не была известна своей обширной способностью манипулировать файловыми дескрипторами в процессе перенаправления.

Вы можете перенаправить как стандартный вывод, так и ошибку в файл с помощью:

xxx >& filename

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


Однако, если ваша базовая операционная система предоставляет стандартный вывод процесса в файловой системе (как это делает Linux с /dev/stdout), вы можете использовать этот метод следующим образом:

xxx >& /dev/stdout

Это заставит как стандартный вывод , так и стандартную ошибку перейти в то же место, что и текущий стандартный вывод, фактически то, что у вас есть с перенаправлением bash, 2>&1.

Просто имейте в виду, что это не функция csh. Если вы работаете в операционной системе, которая не предоставляет стандартный вывод в виде файла, вы не можете использовать этот метод.


Однако есть и другой метод. Вы можете объединить два потока в один, если отправите его в конвейер с помощью |&, тогда все, что вам нужно сделать, это найти компонент конвейера, который записывает свой стандартный ввод в свой стандартный вывод. В случае, если вы не знаете о такой вещи, это именно то, что cat делает, если вы не приводите никаких аргументов. Следовательно, вы можете достичь своих целей в этом конкретном случае с помощью:

xxx |& cat

Конечно, ничто не мешает вам запустить bash (при условии, что он находится где-то в системе) внутри скрипта csh, чтобы получить дополнительные возможности. Затем вы можете использовать богатые перенаправления этой оболочки для более сложных случаев, когда csh может вызывать затруднения.

Давайте рассмотрим это более подробно. Сначала создайте исполняемый файл echo_err, который будет записывать строку в stderr:

#include <stdio.h>
int main (int argc, char *argv[]) {
    fprintf (stderr, "stderr (%s)\n", (argc > 1) ? argv[1] : "?");
    return 0;
}

Затем управляющий скрипт test.csh, который покажет его в действии:

#!/usr/bin/csh

ps -ef ; echo ; echo $$ ; echo

echo 'stdout (csh)'
./echo_err csh

bash -c "( echo 'stdout (bash)' ; ./echo_err bash ) 2>&1"

echo PID и ps нужны просто для того, чтобы вы могли убедиться, что этот скрипт запущен csh. Когда вы запускаете этот скрипт с помощью:

./test.csh >test.out 2>test.err

(начальное перенаправление настраивается с помощью bash до csh запуска сценария) и просмотрите файлы out/err, вы увидите:

test.out:
    UID     PID    PPID  TTY        STIME     COMMAND
    pax    5708    5364  cons0      11:31:14  /usr/bin/ps
    pax    5364    7364  cons0      11:31:13  /usr/bin/tcsh
    pax    7364       1  cons0      10:44:30  /usr/bin/bash

    5364

    stdout (csh)
    stdout (bash)
    stderr (bash)

test.err:
    stderr (csh)

Вы можете видеть, что процесс test.csh запускается в оболочке C, и что вызов bash оттуда дает вам полную bash возможность перенаправления.

2>&1 в команде bash довольно легко позволяет вам перенаправить стандартную ошибку на текущий стандартный вывод (по желанию) без предварительного знания того, куда в данный момент идет стандартный вывод.

person paxdiablo    schedule 05.12.2012
comment
Привет, это можно сделать с помощью csh, немного изменив ответ bioffe. Вам нужно объединить потоки stderr и stdout, а НЕ в файл. Так что сделайте «xxx |& tee /dev/null», и это приведет к объединению потоков, отправке их в поддельный файл, НО ТАКЖЕ отправке обоих в STDOUT на экране (или где бы вы ни использовали стандартный вывод). Пожалуйста, обновите этот ответ с помощью этой опции. - person mdiehl13; 05.08.2015
comment
@ mdiehl13, на самом деле, это хороший момент, и я не рассматривал его. Однако я не уверен, что tee подходит для этой работы. Отправка данных через tee как на стандартный вывод, так и на /dev/null ничем не отличается от отправки данных через cat на просто стандартный вывод. Поэтому я обновил его с этой опцией, но спасибо за информацию, это очень помогло. - person paxdiablo; 05.08.2015
comment
cmd >& /dev/stderr на самом деле полностью испортил мой сеанс NoMachine, хотя команда была в удаленной системе из этого сеанса. Я проголосовал за этот ответ в прошлом, поэтому, по-видимому, он работал в прошлом, но я предлагаю это второе мнение, чтобы остерегаться. - person esmit; 03.08.2017

Я возражаю против приведенного выше ответа и предоставляю свой собственный. csh ИМЕЕТ эту возможность, и вот как это делается:

xxx |& some_exec # will pipe merged output to your some_exec 

or

xxx |& cat > filename

или если вы просто хотите объединить потоки (в стандартный вывод) и не перенаправлять в файл или some_exec:

xxx |& tee /dev/null
person bioffe    schedule 25.01.2014
comment
@chris, это позволяет вам отправлять stdout и stderr в одно и то же место, но не позволяет передавать стандартную ошибку в стандартный вывод current. Так что, во что бы то ни стало, проголосуйте за него, просто имейте в виду, что это не отвечает на вопрос. То, о чем просил ОП, не может быть выполнено с помощью csh, за исключением использования хитрости временного вызова оболочки bash. - person paxdiablo; 03.07.2014
comment
Хотя в csh нет точного эквивалента, ваш ответ охватывает только вариант использования, когда вы хотите перенаправить как stdout, так и stderr в файл. Этот ответ также демонстрирует, как перенаправить их в канал. - person chris; 03.07.2014
comment
@chris, вопрос касался способа направить stderr на текущий стандартный вывод, а не того, как направить их обоих в совершенно новое место (будь то файл или канал). Последнее можно сделать либо с первой частью моего ответа, либо с этим ответом, но csh не может сделать первое. Если вы читаете вторую часть моего ответа (временно вызывая bash из csh, а теперь расширенную конкретным примером, чтобы, надеюсь, прояснить), это прекрасно. - person paxdiablo; 09.07.2014
comment
невероятно... это решение - лучшее решение для csh. p.s. Я не могу в это поверить, но... решение о том, как объединить stderr с stdout через tee /dev/null, является лучшим. ... чм-ч - person Trevor Boyd Smith; 23.09.2020

Как сказал paxdiablo, вы можете использовать >& для перенаправления как stdout, так и stderr. Однако, если вы хотите, чтобы они были разделены, вы можете использовать следующее:

(command > stdoutfile) >& stderrfile

... как указано выше, перенаправит stdout в stdoutfile и stderr в stderrfile.

person Chris    schedule 23.01.2014
comment
Этот ответ должен иметь больше голосов ИМХО. Есть ли какой-то негативный побочный эффект, которого я не вижу? - person Martin G; 29.07.2014
comment
На мой взгляд, это правильный ответ ... другой принятый ответ не отвечает на вопрос! - person Charbel; 18.12.2014
comment
@Charbel, он не перенаправляет stderr на текущий стандартный вывод, он перенаправляет оба в новое местоположение. - person paxdiablo; 05.08.2015

Как насчет просто

xxx >& /dev/stdout

???

person ChPortos    schedule 07.11.2014
comment
Это действительно дает ответ на вопрос, но, вероятно, его не следует ставить с вопросительными знаками, поскольку похоже, что постер не уверен, отвечает ли это на вопрос. - person Andre Miller; 07.11.2014

   xxx >& filename

Или сделайте это, чтобы увидеть все на экране и перейти к вашему файлу:

  xxx | & tee ./logfile
person Ryan P    schedule 27.02.2015

Я думаю, что это правильный ответ для csh.

xxx >/dev/stderr

Обратите внимание, что большинство csh на самом деле являются tcsh в современных средах:

ремоклер> ls -latr /usr/bin/csh

lrwxrwxrwx 1 root root 9 03.05.2011 13:40 /usr/bin/csh -> /bin/tcsh

используя встроенный оператор обратной кавычки, чтобы изобразить это следующим образом:

echo "`echo 'standard out1'` `echo 'error out1' >/dev/stderr` `echo 'standard out2'`" | tee -a /tmp/test.txt ; cat /tmp/test.txt

если это работает для вас, увеличьте до 1. Другие предложения не работают для моей среды csh.

person Rob    schedule 13.02.2014