介绍一下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. vps搭建个人网盘不二之选—kodexplorer介绍,包含安装步骤

    之前给大家介绍过seafile.h5ai等网盘系统,今天给大家介绍下kodexplorer网盘系统.Kodexplorer,也叫芒果云.可道云.kodcloud,总之名字改了不少.但其本身作为一个网盘 ...

  2. JS - Promise使用详解--摘抄笔记

    第一部分: JS - Promise使用详解1(基本概念.使用优点) 一.promises相关概念 promises 的概念是由 CommonJS 小组的成员在 Promises/A 规范中提出来的. ...

  3. php中注释有关内容

    //单行注释 /*多行注释*/ /** 文档注释 (注意 文档注释与前面的那个多行注释不同)文档注释可以和特定的程序元素相关联 例如 类 函数 常量 变量方法 问了将文档注释与元素相关联 只需要在元素 ...

  4. PSP表格记录功能

    关于王者荣耀交流协会的PSP表格记录功能,就是针对我们平时做表格时候遇到问题的简化与解决.这部分功能可以记录我们开始时间,暂停时间,结束时间,并自动计算出各个时间段的净时间.只要你开始工作时点一下开始 ...

  5. 【Alpha】阶段第四次Scrum Meeting

    [Alpha]阶段第四次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 获取课程评论接口 增加课程接口 赵智源 整合前端进行部署 整合前端进行部署 肖萌威 编写 ...

  6. 按Right-BICEP要求的对任务二的测试用例

    测试方法:Right-BICEP 测试计划 1.Right-结果是否正确? 2.B-是否所有的边界条件都是正确的? 3.P-是否满足性能要求? 4.是否有乘除法? 5.是否有括号? 6.是否有真分数? ...

  7. 201621123037《Java程序设计》第二周学习总结

    #Week02-Java基本语法与类库 1. 本周学习总结 关键词:常量池.对象.null.不可变性.string对象拼接.字符串池 关键概念之间的联系:Java中有常量池,超出常量池以外的就会新开辟 ...

  8. 设计模式PHP篇(三)————适配器模式

    简单的适配器模式: interface Adaptor { public function read(); public function write(); } class File implemen ...

  9. mysql子查询批量找id最大的

    $sql = "select a.id as max_id,a.uid from(SELECT `uid`, idFROM (`users_level_change_log`)WHERE ` ...

  10. SQL中的declare用法

    平时写SQL查询.存储过程都是凭着感觉来,没有探究过SQL的具体语法,一直都是按c#那一套往SQL上模仿,前几天项目中碰到一个问题引起了我对declare定义变量的作用域的兴趣. 大家都知道c#中的局 ...