shellコマンドは$ avrdude -c usbtiny
テキストをstderrに出力します。ヘッドレスなどのコマンドでは読めません。もっと多くのcosはstdoutではありません。テキストをstdoutまたはファイルにしたい。どうすればCでそれを行うことができますか?私は最後の質問で問題を解決しようとしましたが、まだ解決していません。
4 に答える
私は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に複製するdup2
方法は、関数の使用例としてPOSIXページに記載されています。
#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;
}
stderrを取得できるように、Cでコマンドをブロックする必要があります
子プロセスを開始する方法について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()が戻った後に一時ファイルを読み取ることもできます。