博客 > Linux下如何在程序中獲取某個命令執(zhí)行的結(jié)果?
瀏覽量:1259次評論:0次
作者:銳成網(wǎng)絡(luò)整理時間:2024-07-05 17:40:30
Linux下如何在程序中獲取某個命令執(zhí)行的結(jié)果?下面介紹3種方法,分別是使用臨時文件、使用匿名管道以及使用popen,以下是相關(guān)內(nèi)容。
1. 使用臨時文件
1) 使用shell的重定向
將命令輸出重定向到一個臨時文件,在我們的應(yīng)用程序中讀取這個臨時文件,獲得外部命令執(zhí)行結(jié)果,代碼如下所示:
/*************************公眾號:一口Linux*********************************
** Name:popen.c
** Author:yikoupeng
** Date:2024/6/26
** All rights 一口linux reserved!
*************************************************************************/
#include <stdlib.h>
#define MAX_STR_LEN 1024
int mysystem(char* cmdstring, char* tmpfile)
{
char cmd_string[MAX_STR_LEN];
mkstemp(tmpfile);
sprintf(cmd_string, "%s > %s", cmdstring, tmpfile);
return system(cmd_string);
}
int main()
{
int len;
len = mysystem("ls -l","yikou.txt");
printf("len=%d\n",len);
return 0;
}
程序執(zhí)行結(jié)果:
2) freopen標(biāo)準(zhǔn)輸出到文件
/*************************公眾號:一口Linux*********************************
** Name:popen.c
** Author:yikoupeng
** Date:2024/6/26
** All rights 一口linux reserved!
*************************************************************************/
#include <stdlib.h>
int main()
{
if(freopen("file.txt","w",stdout)==NULL)
fprintf(stderr,"error\n");
system("ls -ahl");
printf("This is in the file\n"); //該行信息會保存在file.txt中
fclose(stdout);
return 0;
}
執(zhí)行結(jié)果:
freopen還可以重定向標(biāo)準(zhǔn)輸入。
/*************************公眾號:一口Linux*********************************
** Name:popen.c
** Author:yikoupeng
** Date:2024/6/26
** All rights 一口linux reserved!
*************************************************************************/
//首先在同路徑下創(chuàng)建一個in.txt文本文檔寫入若干數(shù)字
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b;
//從in.txt 中讀入數(shù)據(jù)
freopen("in.txt","r",stdin);
// 將最后數(shù)據(jù)寫入out.txt中
freopen("out.txt","w",stdout);
while(scanf("%d%d",&a,&b)!=EOF) //數(shù)據(jù)是從in.txt中輸入的
printf("%d\n",a+b); //寫入out.txt中
fclose(stdin);
fclose(stdout);
return 0;
}
這種使用使用了臨時文件作為應(yīng)用程序和外部命令之間的聯(lián)系橋梁,在應(yīng)用程序中需要讀取文件,然后再刪除該臨時文件,比較繁瑣,優(yōu)點(diǎn)是實(shí)現(xiàn)簡單,容易理解。
2. 使用匿名管道
還可以通過匿名管道來將外部命令的結(jié)果同應(yīng)用 程序連接起來。
方法:
就是fork一個子進(jìn)程,并創(chuàng)建一個匿名管道,在子進(jìn)程中執(zhí)行shell命令,并將其標(biāo)準(zhǔn)輸出dup到匿名管道的輸入端,父進(jìn)程從管道 中讀取,即可獲得shell命令的輸出,代碼如下:
/*************************公眾號:一口Linux*********************************
** Name:popen.c
** Author:yikoupeng
** Date:2024/6/26
** All rights 一口linux reserved!
* @param[in] cmdstring 調(diào)用外部程序或腳本的命令串
* @param[out] buf 返回外部命令的結(jié)果的緩沖區(qū)
* @param[in] len 緩沖區(qū)buf的長度
*
* @return 0: 成功; -1: 失敗
*************************************************************************/
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) /* parent process */
{
close(fd[1]); /* close write end */
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 /* child process */
{
close(fd[0]); /* close read end */
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;
}
3. 使用popen
Linux還提供了一個popen函數(shù),可以非常簡單的處理調(diào)用shell,其函數(shù)原型如下:
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
該函數(shù)的作用是創(chuàng)建一個管道,fork一個進(jìn)程,然后執(zhí)行shell,而shell的輸出可以采用讀取文件的方式獲得。
參數(shù):
command:要執(zhí)行的命令
type:popen 通過type是r還是w確定command的輸入/輸出方向,r和w是相對command的管道而言的。
r:表示command從管道中讀入,
w:表示 command通過管道輸出到它的stdout,popen返回FIFO管道的文件流指針。pclose則用于使用結(jié)束后關(guān)閉這個指針。
例1:popen
/*************************公眾號:一口Linux*********************************
** Name:popen.c
** This program is used to show the usage of popen() .
** Author:yikoupeng
** Date:2024/6/26
** All rights 一口linux reserved!
*************************************************************************/
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main( void )
{
FILE *stream;
FILE *wstream;
char buf[1024];
memset( buf, '\0', sizeof(buf) );
/*將“ls /dev”命令的輸出 通過管道讀取(“r”參數(shù))到FILE* stream*/
stream = popen( "ls -l", "r" );
/*新建一個可寫的文件*/
wstream = fopen( "test_popen.txt", "w+");
/*將剛剛FILE* stream的數(shù)據(jù)流讀取到buf中*/
fread( buf, sizeof(char), sizeof(buf), stream);
/*將buf中的數(shù)據(jù)寫到FILE *wstream對應(yīng)的流中,同時也寫到文件中*/
fwrite( buf, 1, sizeof(buf), wstream );
//關(guān)閉文件句柄
pclose( stream );
fclose( wstream );
return 0;
}
例2:getline讀取一行【推薦使用】
使用getline函數(shù)直接從popen返回的數(shù)據(jù)流中讀取數(shù)據(jù):
#include <stdio.h>
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
函數(shù)getline可以從流stream中讀取一整行,數(shù)據(jù)保存在***lineptr**中
參數(shù)
lineptr :二級指針,該函數(shù)會為我們申請內(nèi)存,并通過lineptr指向該內(nèi)存,所以使用完畢需要free該內(nèi)存
n:實(shí)際分配的內(nèi)存大小
stream:popen()打開的流
返回值:
成功:返回實(shí)際讀取字節(jié)個數(shù),包括delimiter字符,但是不包括字符串結(jié)束符**\0**
出錯:-1
/*************************公眾號:一口Linux*********************************
** Name:popen.c
** This program is used to show the usage of popen() .
** Author:yikoupeng
** Date:2024/6/26
** All rights 一口linux reserved!
*************************************************************************/
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main (void)
{
FILE *stream;
char *line = NULL;
size_t len = 0;
ssize_t read;
stream = popen ("ls -l", "r");
while ((read = getline (&line, &len, stream)) != -1)
{
printf ("len=%zu read:%zu:\n", len,read);
printf ("%s", line);
}
free(line);
pclose (stream);
return 0;
}
命令執(zhí)行結(jié)果
peng@ubuntu:~/work/test/open$ ls -l
total 16
-rw-rw-r-- 1 peng peng 382 Jun 22 10:04 popen.c
-rwxrwxr-x 1 peng peng 8824 Jun 22 10:04 run
程序執(zhí)行結(jié)果
結(jié)論
采用popen()函數(shù),既避免了創(chuàng)建臨時文件,又不受輸出字符數(shù)的限制,配合getline使用,更加方便,推薦使用。
重要聲明:本文來自一口Linux,經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有,不代表銳成觀點(diǎn),轉(zhuǎn)載的目的在于傳遞更多知識和信息。
相關(guān)文章推薦
2025-05-27 11:53:22
2024-08-20 17:58:16
2024-08-19 17:49:29
2024-08-19 10:23:28
2024-08-16 17:06:33
熱門工具
標(biāo)簽選擇
閱讀排行
我的評論
還未登錄?點(diǎn)擊登錄