介绍一下Linux系统中的代码执行shell等命令的几种操作方式:

一、标准流管道popen

该函数的原型是FILE * popen(const char* command, const char *type);

command:使我们要执行的命令,即上述的运行命令,

type:有两种可能的取值,“r”(代表读取)或者“w"(代表写入)

popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh-c来执行参数command的指令,参数type可使用“r”读取 或者“w”写入,根据type的值,popen()会创建管道连接到子进程的标准输出设备或者标准输入设备,然后返回一个文件指针。随后进程就可以利用此文件指针来读取子进程的标准输出设备或者写入子进程的标准输入设备。

这个函数可以大大减少代码的编写量,但使用不太灵活,不能自己创建管道那么灵活,并且popen()必须使用标准的I/o函数进行操作,也不能使用read(),wirte()这种不带缓冲的I/O函数,必须使用pclose()来关闭管道流,该函数关闭标准I/O流,并等待命令执行结束

个人总结:记住,向这个流中写内容相当于写入该命令(或者是该程序)标准输入; 向这个流中读数据相当于读取该命令(或者是该程序)的标准输出

写例子:

#include<stdio.h>

#include<unistd.h>

#include<stdlib.h>

#include<fcntl.h>

int main()

{

FILE *fp;

char *cmd="cat > aaa";   ///该命令新建一个文件,提示用户输入数据作为其内容

char buf[1000]="ni hao wo de peng you!\n";  ///待输入的参数

if((fp=popen(cmd,"w"))==NULL)

return 1;

fwrite(buf,sizeof(char),1000,fp);   ///通过文件描述符写入文件数据

pclose(fp); ///关闭文件描述符

exit(0);

return 0;

}

读例子:

LD_S32 RunSysCmd2(LD_CS8 *pCmd, LD_S8 *pRslBuf, LD_S32 bufSz)

{

LD_S32 ret = LD_FAILURE;

FILE *pFd = popen(pCmd, "r");//创建一个流管道生成一个子进程用于执行命令

if(pFd)

{

memset(pRslBuf, 0, bufSz);

if(fread(pRslBuf, bufSz - 1, 1, pFd) >= 0)//从该命令中读取数据

{

ret = LD_SUCCESS;

}

pclose(pFd);//关闭流管道

}

return ret;

}

二、system

system("cat "Read pipe successfully!" > test1")

三、exec

在Linux中,并不存在exec()函数,exec指的是一组函数,一共有6个,分别是:

#include <unistd.h>

extern char **environ;

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);

int execve(const char *path, char *const argv[], char *const envp[]);

其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。

exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息。
  bash shell的命令分为两类:外部命令和内部命令。外部命令是通过系统调用或独立的程序实现的,如sed、awk等等。内部

命令是由特殊的文件格式(.def)所实现,如cd、history、exec等等。

  在说明exe和source的区别之前,先说明一下fork的概念。

  fork是linux的系统调用,用来创建子进程(child process)。子进程是父进程(parent process)的一个副本,从父进程那里

获得一定的资源分配以及继承父进程的环境。子进程与父进程唯一不同的地方在于pid(process id)。

  环境变量(传给子进程的变量,遗传性是本地变量和环境变量的根本区别)只能单向从父进程传给子进程。不管子进程的环境

变量如何变化,都不会影响父进程的环境变量。

  shell
script:

  有两种方法执行shell
scripts,一种是新产生一个shell,然后执行相应的shell
scripts;一种是在当前shell下执行,不

再启用其他shell。

  新产生一个shell然后再执行scripts的方法是在scripts文件开头加入以下语句

  #!/bin/sh

  一般的script文件(.sh)即是这种用法。这种方法先启用新的sub-shell(新的子进程),然后在其下执行命令。

  另外一种方法就是上面说过的source命令,不再产生新的shell,而在当前shell下执行一切命令。

  source:

  source命令即点(.)命令。

  在bash下输入man source,找到source命令解释处,可以看到解释”Read and execute commands from filename in the

current shell
environment and …”。从中可以知道,source命令是在当前进程中执行参数文件中的各个命令,而不是另起子

进程(或sub-shell)。

  exec:

  在bash下输入man exec,找到exec命令解释处,可以看到有”No new process is created.”这样的解释,这就是说exec命

令不产生新的子进程。那么exec与source的区别是什么呢?

  exec命令在执行时会把当前的shell process关闭,然后换到后面的命令继续执行。

系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的

进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。

popen,system和exec区别:

1.system和popen都是执行了类似的运行流程,大致是fork->execl->return。但是我们看到system在执行期间调用进程会一直等待shell命令执行完成(waitpid等待子进程结束)才返回,但是popen无须等待shell命令执行完成就返回了。我们可以理解system为串行执行,在执行期间调用进程放弃了”控制权”,popen为并行执行。

2.popen中的子进程没人给它”收尸”了啊?是的,如果你没有在调用popen后调用pclose那么这个子进程就可能变成”僵尸”。

3.对于管道已经很清楚,而管道写可能用的地方比较少。而对于写可能更常用的是system函数:

system("cat "Read pipe successfully!"
> test1")

4.如果不需要使用到程序的I/O数据流,那么system是最方便的。

而且system函数是C89和C99中标准定义的,可以跨平台使用。而popen是Posix 标准函数,可能在某些平台无法使用(windows应该是可以的吧,没做过测试)。

5.可以看出,popen可以控制程序的输入或者输出,而system的功能明显要弱一点,比如无法将读取结果用于程序中。

6.如果上述两个函数还无法满足你的交互需求,那么可以考虑exec函数组了。

system是用shell来调用程序=fork+exec+waitpid,而exec是直接让你的程序代替原来的程序运行。

system 是在单独的进程中执行命令,完了还会回到你的程序中。而exec函数是直接在你的进程中执行新的程序,新的程序会把你的程序覆盖,除非调用出错,否则你再也回不到exec后面的代码,就是说你的程序就变成了exec调用的那个程序了。

最后说一下exit函数:

exit是一个库函数,exit(1)表示发生错误后退出程序,   exit(0)表示正常退出。

对你的程序来说,没有区别。对使用你的程序的人或者程序来说,区别可就大了。

一般来说,exit 0 可以告知你的程序的使用者:你的程序是正常结束的。如果 exit 非 0 值,那么你的程序的使用者通常会认为你的程序产生了一个错误。

以 shell 为例,在 shell 中调用完你的程序之后,用 echo $? 命令就可以看到你的程序的 exit 值。在 shell 脚

本中,通常会根据上一个命令的 $? 值来进行一些流程控制。

同样的情形出现在 C 语言的 exec 系列函数中。

例:

当你 exit 0 的时候,在调用环境 echo $? 就返回0,也就是说调用环境就认为你的这个程序执行正确

当你 exit 1 的时候,一般是出错定义这个1,也可以是其他数字,很多系统程序这个错误编号是有约定的含义的。

但不为0 就表示程序运行出错。 调用环境就可以根据这个返回值判断 你这个程序运行是否ok。搜索如果你用 脚本 a 调用 脚本b
,要在a中判断b是否正常返回,就是根据 exit 0 or 1 来识别。执行完b后, 判断 $? 就是返回值

Linux之执行命令操作20170330的更多相关文章

  1. Linux后台执行命令:&和nohup nohup和&后台运行,进程查看及终止

    nohup和&后台运行,进程查看及终止   阅读目录 nohup和&后台运行,进程查看及终止 1.nohup 2.& 3.nohup和&的区别 &:是指在后台运 ...

  2. linux中执行命令权限不够怎样处理

    在linux中执行命令权限不够就要增加权限,先看遇到的情况 查看权限情况 那就赋予权限 执行命令

  3. Android 开发进入Linux系统执行命令 2018-5-25 Fri.

    /** * 进入linux cmd执行命令 * * @param command * @return */ private boolean runRootCommand(String command) ...

  4. [转帖]Linux后端执行命令的方法

    Linux 后台执行命令的方法 http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=4241330&fromuid=212883 ...

  5. expect 交互 之shell执行命令操作

    shell 执行命令操作 /usr/bin/expect -c " proc jiaohu {} { send_user expect_start expect { password { s ...

  6. Shell脚本中实现切换用户并执行命令操作【转】

    第一种方法 cat test.sh #!/bin/bashsu - test <<EOFpwd;exit;EOF 执行结果图: 第二种方法 当然也可以用下面的命令来执行 复制代码代码如下: ...

  7. java使用ssh连接Linux并执行命令

     方式1:通过设置账号密码和链接地址 maven pom.xml配置: <dependency>         <groupId>com.jcraft</groupId ...

  8. php 执行计划任务方式之 linux crontab 执行命令

    一.crond简介 crond 是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务 工具,并且会自动启动c ...

  9. 初学Linux基本的命令操作应当记牢

    Linux管理文件和目录的命令 命令 功能 命令 功能 pwd 显示当前目录 ls 查看目录下的内容 cd 改变所在目录 cat 显示文件的内容 grep 在文件中查找某字符 cp 复制文件 touc ...

随机推荐

  1. Jenkins Git安装设置

    Jenkins Git安装设置 在此安装中,必须确保Internet连接可连接其安装 Jenkins 机器.在 Jenkins 仪表盘(主屏幕)的左侧单击 Manage Jenkins 选项.打开网址 ...

  2. 第k小分数(二分值)

    //时间限制:10000ms //单点时限:1000ms //内存限制:256MB //描述 //给定N个不同的质数P1, P2, … PN.用它们作为分目可以组成(P1-1) + (P2-1) + ...

  3. 爬虫2.5-scrapy框架-下载中间件

    目录 scrapy框架-下载中间件 scrapy框架-下载中间件 middlewares.py中有两个类,一个是xxSpiderMiddleware类 一个是xxDownloaderMiddlewar ...

  4. Hyperledger中的共识机制

    Hyperledger Consensus 共识过程 Hyperlydger中建立共识的过程由以下两个独立的过程构成: Ordering of transactions (交易排序) Validati ...

  5. Github上的一些高分Qt开源项目【多图】

    游戏2D地图编辑器: 著名的TileMap编辑器,做2D游戏开发的一定不会陌生. Go 语言的IDE: Go语言的集成开发环境. Clementine Music Player: 功能很完善且跨平台支 ...

  6. 3.Airflow使用

    1. airflow简介2. 相关概念2.1 服务进程2.1.1. web server2.1.2. scheduler2.1.3. worker2.1.4. celery flower2.2 相关概 ...

  7. moment.js学习总结

    一. 介绍: moment.js不依赖任何第三方库,支持字符串.Date.时间戳以及数组等格式,可以像PHP的date()函数一样,格式化日期时间,计算相对时间,获取特定时间后的日期时间等等.下面是一 ...

  8. LeetCode 289. Game of Life (C++)

    题目: According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a ce ...

  9. 【java】中缀表达式转后缀表达式 java实现

    算法: 中缀表达式转后缀表达式的方法:1.遇到操作数:直接输出(添加到后缀表达式中)2.栈为空时,遇到运算符,直接入栈3.遇到左括号:将其入栈4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出 ...

  10. ext4.1入门

    ExtJS简介 Ext是一个Ajax框架,用于在客户端创建丰富多彩的web应用程序界面,是在Yahoo!UI的基础上发展而来的.官方网址:www.sencha.com ExtJS是一个用来开发前端应用 ...