Linuxプログラムからshell(プログラム、スクリプト)を実行し、出力結果を得る.

4561 ワード

本論文の転送先:http://hi.baidu.com/tihu1111/blog/item/98e41c3d3a621ae23c6d9744.html
 
Linuxプログラムからshell(プログラム、スクリプト)を実行し、出力結果(転送)を得る.
コンテント
1.はじめに
2.一時ファイルを使う
3.匿名のパイプを使う
4.popenを使う
5.まとめ
1.はじめに
Unix界の名言に「1行のshellシナリオは万行Cプログラムに勝る」というのがあります.この言葉は誇張していますが、脚本を通してかなりのプログラム作業を簡略化できることは否定できません.例えば、pingプログラムを実現してネットワークの接続性をテストします.ping関数を実現するには200~300行のコードを記入する必要があります.なぜ直接システムのpingコマンドを呼び出すことができないですか?通常はプログラムでsystem関数でshellコマンドを呼び出します.しかし、system関数はコマンドが実行に成功したかどうかだけを返します.私たちは、shellコマンドがコンソール上で出力された結果を得る必要があります.例えば、外部コマンドpingを実行した後、実行に失敗したら、pingの戻り情報を取得したいです.
2.一時ファイルを使う
まず思いつく方法は、コマンド出力を一時ファイルにリダイレクトし、私たちのアプリケーションでこの一時ファイルを読み込み、外部コマンド実行結果を得ることです.コードは以下の通りです.
    #define CMD_STR_LEN  1024
int mysystem(char* cmdstring, char* tmpfile)
{
char cmd_string[CMD_STR_LEN];
tmpnam(tmpfile);
sprintf(cmd_string, "%s > %s", cmdstring, tmpfile);
return system(cmd_string);
}
このような一時ファイルは、アプリケーションと外部コマンドとの間の連絡橋として使用されています.アプリケーションではファイルを読み込む必要があります.そして、その一時ファイルを削除するのは、煩雑で、簡単で分かりやすいという利点があります.臨時書類を使わない方法がありますか?
3.匿名のパイプを使う
「UNIX環境高級プログラミング」には、匿名のパイプでプログラム結果を改ページプログラムに出力する例が記載されていますので、外部コマンドの結果を配管でアプリケーションに接続することもできます.方法はforkのサブプロセスであり、匿名のパイプラインを作成し、サブプロセスでshellコマンドを実行し、その標準をdupから匿名のパイプラインの入力端子に出力し、親プロセスはパイプから読み取れば、shellコマンドの出力が得られます.コードは以下の通りです.
  
int mysystem(char* cmdstring, char* buf, int len)
{
int fd[2];
pid_t pid;
int n, count;
memset(buf, 0, len);
if (pipe(fd) < 0)
return -1;
if ((pid = fork()) < 0)
return -1;
else if (pid > 0)
{
close(fd[1]);
count = 0;
while ((n = read(fd[0], buf + count, len)) > 0 && count > len)
count += n;
close(fd[0]);
if (waitpid(pid, NULL, 0) > 0)
return -1;
}
else
{
close(fd[0]);
if (fd[1] != STDOUT_FILENO)
{
if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
{
return -1;
}
close(fd[1]);
}
if (execl("/bin/sh", "sh", "-c", cmdstring, (char*)0) == -1)
return -1;
}
return 0;
}
4.popenを使う
unixプログラミングを学習する過程で、システムはまたpopen関数を提供しています.非常に簡単な処理でshellを呼び出すことができます.その関数のプロトタイプは以下の通りです.
FILE *popen(const char *command, const char *type);
この関数の役割はパイプを作成し、プロセスをforkしてshellを実行することであり、shellの出力はファイルを読み込む方式で得ることができる.この方法では、一時ファイルを作成することも、出力文字数に制限されることもなく、推奨されています.
popenはFIFOパイプを使って外部プログラムを実行します.includeFILE*popen;int pclose(FILE*stream)popenはtypeがrかwかでcommandの入出力方向を確定します.rとwは比較的commandの配管です.rはcommandが配管から読み込むことを示し、wはcommandがパイプを通してそのstdoutに出力し、popenがFIFOパイプのファイルフローポインタに戻ることを示している.pcloseは使用終了後にこのポインタを閉じるために使用します.以下の例を見てください.萝include胫include胭胫include胫嗳嗳嗳;嗳inudio;œĹindcleint main;(void)/fibuem/fibuem;文字化けはファイルの中でstream=popen(「ls-l」「r」)/「ls-l」になります.命令の出力はパイプを通してFILE*streemwstream=fopen(「testupopen.txt」、「w+」)を読み取ります./書き取り可能なファイルfread(buf、sizeof(char)、sizef(buf)、stream)を新規作成します.;/FILE*wstream対応のストリームにbufのデータを書き込み、ファイルの中のpclose(stream);fclose(wstream);return 0;[root@localhostsrc.⑵唵gcc popen.root@localhostsrc./(zhi)/a.out[root@localhostsrc]菵cat test_popen.txt合計12-rwxr-x 1 root root 5558 09-30 11:51 a.out rwxr-x 1 root root 542 09-30 00:00 child_fork.cd-rwxr-xr-x 1 root root 480 09-30 00:13 execve.c- rwxr-xr-x 1 root-x 1 rootot 1811 09-29 21:33 Fok.ccr-xr-x 1 rootot 162 09 09-21 09 09 09 09 09 09 09-21:54 getpid.cd.cd.cr r r r r r-cxxxxr r r r r 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010-18 18 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09-18 18 18 18 18 18 18:xr-xr-x 1 root root 0 09-30 11:51 test_popen.txt-rwxr-x 1 root root 4094 09-30 11:39 test.txt
5.まとめ
統計データによると、コードの欠陥率は一定であり、使用言語とは無関係である.Linuxは多くの実用的なツールとスクリプトを提供しています.プログラムでツールとスクリプトを呼び出すと、プログラムを簡単にすることができ、コードの欠陥の数を減らすことができます.Linux shellスクリプトも強力なツールであり、必要に応じてスクリプトを作成し、その後、プログラムでカスタマイズスクリプトを呼び出すことができます.