C: كيفية إعادة توجيه STDERR من نظام النظام إلى stdout أو ملف؟

StackOverflow https://stackoverflow.com/questions/3019630

سؤال

أمر شل $ avrdude -c usbtiny يخرج النص إلى Stderr. لا يمكنني قراءتها مع commmands مثل القسم الخالي من القسم ، فهي ليست stdout. أريد النص إلى stdout أو إلى ملف. كيف يمكنني فعل ذلك في ج؟ لقد حاولت حل المشكلة سؤالي الأخير ولكن لا يزال دون حل.

هل كانت مفيدة؟

المحلول

لم أجرب شيئًا كهذا في 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");
}

نصائح أخرى

الطريقة العادية ستكون مثل:

avrdude -c usbtiny 2>&1

هذا يوجه ما يمكن أن يذهب عادة إلى Stderr للذهاب إلى stdout بدلا من ذلك. إذا كنت تفضل توجيهه إلى ملف ، فيمكنك فعل شيء مثل:

avrdude -c usbtiny 2> outputfile.txt

يستخدم ما يلي وظيفة 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;
}

أحتاج إلى حظر الأمر بطريقة ما في 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) للطفل بنهاية كتابة للأنبوب. يتم استدعاء الأنابيب () قبل شوكة (). بعد الشوكة ، علينا أيضًا إغلاق الجميع شنق نهايات الأنبوب بحيث تتلقى القراءة في عملية الوالدين بالفعل EOF.

ربما يكون هناك حل أبسط باستخدام STDIO ، لكنني لست على علم بذلك. نظرًا لأن Popen () يدير الأمر عبر shell ، فربما يمكن للمرء أن يخبره بإعادة توجيه Stderr إلى stdout (وإرسال stdout إلى /dev /null). لم تحاول ذلك.

يمكن للمرء أيضًا استخدام mktemp () (man 3 mktemp) لإنشاء اسم ملف temp ، compose command for system () لإعادة توجيه stderr من الأمر إلى ملف temp وبعد إرجاع النظام () اقرأ ملف temp.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top