C: come redirect stderr da System-command a stdout o file?

Il comando shell $ avrdude -c usbtiny restituisce il testo a stderr. Non riesco a leggerlo con commmands come head-less-more cos non è stdout. Voglio il testo sullo standard o su un file. Come posso farlo in C? Ho cercato di risolvere il problema con la mia ultima domanda, ma ancora non risolto.

Non ho provato qualcosa di simile in OpenBSD, ma in almeno alcuni sistemi * nix-like, puoi farlo usando dup2 .

 #include  #include  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"); } 

Il modo normale sarebbe qualcosa di simile:

 avrdude -c usbtiny 2>&1 

Questo dirige quello che normalmente andrebbe a stderr per andare invece allo stdout. Se preferisci indirizzarlo a un file, puoi fare qualcosa come:

 avrdude -c usbtiny 2> outputfile.txt 

Di seguito viene utilizzata la funzione POSIX per duplicare il numero di file di output standard nel numero di file di errore standard. La duplicazione di stderr su stdout viene fornita nella pagina POSIX per dup2 come esempio di utilizzo della funzione.

 #include  #include  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; } 

Ho bisogno di bloccare in qualche modo il comando in C in modo da poter ottenere il suo stderr

Inizia leggendo man fork , man exec su come avviare un processo figlio. Guarda il man 7 signal , l’ man sigaction e l’ man wait come raccogliere il bambino.

Finalmente, l’ man dup2 .

Codice non testato per esemplificare:

 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 ); } 

Usando dup2 () sostituiamo stderr (che è fd 2) del bambino con una fine di scrittura di una pipe. pipe () viene chiamato prima di fork (). Dopo la forchetta, dobbiamo anche chiudere tutte le estremità sospese del tubo in modo che la lettura nel processo padre possa effettivamente ricevere EOF.

Probabilmente esiste una soluzione più semplice con stdio, ma non ne sono a conoscenza. Poichè popen () esegue il comando tramite shell, probabilmente si può dire di redirect stderr a stdout (e inviare stdout a / dev / null). Non ci ho mai provato.

Si può anche usare mktemp () ( man 3 mktemp ) per creare un nome di file temporaneo, comporre il comando per system () per redirect lo stderr del comando nel file temp e dopo system () ritorna leggere il file temp.