C++ の system()関数
-
C++ の
system()
関数を使用してシェルコマンドを実行する -
システムで
system(nullptr)
を使用してシェルが使用可能かどうかを確認する -
wstatus
マクロを使用して、実行されたコマンドのステータスを確認する
この記事では、C++ でライブラリ関数 system()
を使用する複数の方法について説明します。
C++ の system()
関数を使用してシェルコマンドを実行する
system()
関数はしばらくの間 C 標準ライブラリの一部であり、追加のライブラリなしで C++ コードに含めることもできます。この関数は、呼び出しプロセスからシェルコマンドを実行するために使用されます。ただし、システム
は、呼び出し元のプログラムが単一の子プロセスを生成し、すぐにその終了を待機し始める必要がある特別なユースケースのために作成されていることに注意してください。したがって、関数自体は、システムインターフェイスの一部として使用できる複数のシステムコールで実装されます。
UNIX 環境を想定している場合、ユーザーは、新しいプロセスの作成/クリーンアップを制御する fork
、exec
、および wait
関数を直接処理する必要はありません。次の例は、system
関数の最も単純な使用例を示しています。この関数は、ls
コマンドラインユーティリティを実行して、現在の作業ディレクトリにあるファイルを出力します。
#include <iostream>
int main() {
system("ls");
return EXIT_SUCCESS;
}
system()
関数は通常、1つのコマンドを実行するために 2つのプロセスを作成します。つまり、シェルが実行する特定のコマンドに対して、1つの exec
呼び出しと別の呼び出しでシェルを作成します。基盤となるシステムコールを直接使用する場合に比べて、パフォーマンスに悪影響を及ぼします。system
で top
コマンドを実行すると、プログラムはユーザーが手動で top
を終了するまで待機します。これにより、呼び出しプロセスに戻り、に示すように強制的に return
ステートメントに移動します。次の例。
#include <iostream>
int main() {
system("top");
return EXIT_SUCCESS;
}
システムで system(nullptr)
を使用してシェルが使用可能かどうかを確認する
system()
関数は、引数として 1 文字の文字列を取ります。これは、シェルから実行する必要のあるコマンドです。nullptr
または NULL
を渡すと、システムでシェルプログラムが使用可能になったときにゼロ以外の値が返されます。ゼロが返された場合は、シェルが使用できないことを示します。
#include <iostream>
#include <string>
using std::cout;
using std::endl;
int main() {
auto ret = system(nullptr);
if (ret != 0)
cout << "shell is available on the system!" << endl;
else
cout << "shell is not available on the system!" << endl;
return EXIT_SUCCESS;
}
出力:
shell is available on the system!
wstatus
マクロを使用して、実行されたコマンドのステータスを確認する
system
呼び出しが子プロセスの作成に失敗した場合、-1
を返し、それに応じて errno
を設定します。関数呼び出しが成功した場合、戻り値は、指定されたコマンドを実行したシェルの終了ステータスコードです。また、この終了ステータスコードは、最後に実行されたコマンドの終了コードと同じです。したがって、wait
システムコール man ページで説明されている wstatus
マクロを使用して、その値を調べることができます。次のコードスニペットは、printWaitStatus
関数を実装して、system
の戻り値をチェックし、最後に実行されたコマンドに関する詳細を出力します。
#include <cstring>
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::string;
void printWaitStatus(const char *msg, int status) {
if (msg != nullptr) printf("%s", msg);
if (WIFEXITED(status)) {
printf("child exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("child killed by signal %d (%s)", WTERMSIG(status),
strsignal(WTERMSIG(status)));
#ifdef WCOREDUMP
if (WCOREDUMP(status)) printf(" (core dumped)");
#endif
printf("\n");
} else if (WIFSTOPPED(status)) {
printf("child stopped by signal %d (%s)\n", WSTOPSIG(status),
strsignal(WSTOPSIG(status)));
#ifdef WIFCONTINUED
} else if (WIFCONTINUED(status)) {
printf("child continued\n");
#endif
} else {
printf("status=%x\n", (unsigned int)status);
}
}
int main() {
auto ret = system("ls");
if (ret == -1)
cout << "a child process could not be created, or"
"its status could not be retrieved!"
<< endl;
else
printWaitStatus(nullptr, ret);
return EXIT_SUCCESS;
}
出力:
(ls command output)
...
child exited, status=0