C: как перенаправить stderr из системной команды в стандартный вывод или файл? - PullRequest
8 голосов
/ 11 июня 2010

Команда оболочки $ avrdude -c usbtiny выводит текст в stderr.Я не могу прочитать его с помощью таких команд, как head-less-more, потому что это не стандартный вывод.Я хочу, чтобы текст на стандартный вывод или в файл.Как я могу сделать это в C?Я попытался решить проблему с помощью моего последнего вопроса , но все еще не решен.

Ответы [ 4 ]

16 голосов
/ 11 июня 2010

Я не пробовал что-то подобное в OpenBSD, но по крайней мере в нескольких * nix-подобных системах вы можете сделать это, используя dup2.

#include <unistd.h>
#include <stdio.h>

int main(void) {  

  fprintf(stderr, "This goes to stderr\n");

  dup2(1, 2);  //redirects stderr to stdout below this line.

  fprintf(stderr, "This goes to stdout\n");
}
3 голосов
/ 11 июня 2010

Нормальным способом будет что-то вроде:

avrdude -c usbtiny 2>&1

Это указывает, что обычно идет в stderr вместо stdout. Если вы предпочитаете направить его в файл, вы можете сделать что-то вроде:

avrdude -c usbtiny 2> outputfile.txt
0 голосов
/ 11 июня 2010

Мне нужно как-то заблокировать команду в C, чтобы я мог получить ее stderr

Начните с чтения man fork, man exec о том, как запустить дочерний процесс.Посмотрите на man 7 signal, man sigaction и man wait, как пожать ребенка.

Наконец, man dup2.

Непроверенный код для примера:

int pip_stderr[2];
int r;
int pid;

r = pipe(pip_stderr);
assert( r != -1 );

int pid = fork();
assert( pid != -1 );
if (pid == 0) { /* child */
   /* child doesn't need to read from stderr */
   r = close(pip_stderr[0]); assert( r != -1 );
   /* make fd 2 to be the writing end of the pipe */
   r = dup2(pip_stderr[1], 2); assert( r != -1 );
   /* close the now redundant writing end of the pipe */
   r = close(pip_stderr[1]); assert( r != -1 );
   /* fire! */
   exec( /* whatever */ );
   assert( !"exec failed!" );
} else { /* parent */
   /* must: close writing end of the pipe */
   r = close( pip_stderr[1] ); assert( r != -1 );

   /* here read from the pip_stderr[0] */

   r = waitpid(pid,0,0); assert( r == pid );
}

Используя dup2 (), мы заменяем stderr (который является fd 2) дочернего элемента записывающим концом канала.pipe () вызывается перед fork ().После разветвления мы также должны закрыть все висячие концы канала, чтобы чтение в родительском процессе фактически получило EOF.

Возможно, есть более простое решение с использованием stdio, но яне осознавая этого.Поскольку popen () запускает команду через оболочку, возможно, можно сказать ей перенаправить stderr в stdout (и отправить stdout в / dev / null).Никогда не пробовал.

Можно также использовать mktemp () (man 3 mktemp) для создания имени временного файла, составить команду для system (), чтобы перенаправить stderr команды во временный файл и после system ()возвращает прочитанный временный файл.

0 голосов
/ 11 июня 2010

Далее используется функция POSIX для дублирования стандартного номера выходного файла в стандартный номер файла ошибок.Дублирование stderr в stdout приведено на странице POSIX для dup2 в качестве примера использования функции.

#include <unistd.h>
#include <stdio.h>

int main (void)
{
    pid_t child = fork();

    if (child == 0)
    {
        dup2(STDOUT_FILENO, STDERR_FILENO);
        execlp("avrdude", "-c", "usbtiny", NULL);
    }
    else if (child > 0)
    {
        waitpid(child);
        puts("Done!");
    }
    else
    {
        puts("Error in forking :(");
    }

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...