c++中运行shell脚本一般有三种方法,分别是system、exec和popen,都是调用
/bin/sh来执行参数指定的命令,/bin/sh 一般是一个软连接,指向某个具体的shell,比如bash,-c选项是告诉shell从字符串command中读取命令;
在该command执行期间,SIGCHLD是被阻塞的,好比在说:hi,内核,这会不要给我送SIGCHLD信号,等我忙完再说;
在该command执行期间,SIGINT和SIGQUIT是被忽略的,意思是进程收到这两个信号后没有任何动作。
system执行步骤:
1.fork一个子进程;
2.在子进程中调用exec函数去执行command;
3.在父进程中调用wait去等待子进程结束。
对于fork失败,system()函数返回-1。
如果exec执行成功,也即command顺利执行完毕,则返回command通过exit或return返回的值。
(注意,command顺利执行不代表执行成功,比如command:"rm debuglog.txt",不管文件存不存在该command都顺利执行了)
如果exec执行失败,也即command没有顺利执行,比如被信号中断,或者command命令根本不存在,system()函数返回127.
如果command为NULL,则system()函数返回非0值,一般为1.
最近写了c++shell混合编程,用到了system和popen函数,其中system函数只有运行成功与否的,不能从脚本里面取出变量值,只能获取shell是否运行成功的取值,成功返回0,失败返回-1。具体实现是
int ret, status;
ret = system(" ./xxx.sh");
if (WIFEXITED(ret)) {
status = WEXITSTATUS(status);
} else {
status = -1;
}
是利用WEXITSTATUS这个宏来监听实现运行成功与否。当然命令行也可以用$?来实现。
popen函数是利用管道来实现对于脚本和脚本内数据的读取,可以 对脚本内的变量进行赋值,然后利用popen的"r"功能取出来,N=“1”//赋值,"="中间不能有空格
echo $N//提取变量
具体实现先定义文件指针,再创建一个字符数组。
FILE *stream;//
char buffer[12];
static int ret = 0;
memset(buffer,'\0',sizeof(buffer));//清零
system("chmod 777 VerifyNand.sh");//加权限
stream = popen("./VerifyNand.sh","r");//运行脚本,用只读方式打开脚本,读取脚本变量
printf("script runing...\n");//log,便于掌握程序跑到哪里了
if((stream = popen("./VerifyNand.sh","r")) != NULL)//判断是否为空,等于则是打开失败
{
printf("VerifyNand script error\n");
exit(1);
}
else
while(fgets(buffer,sizeof(buffer),stream))//用fgets函数循环读取,自动最后加\0,遇空停止,一行一行读取,这个函数还有待研究,我在这里使用有bug
{
int x = 0;
ret = buffer[x] - '0';//转变成int数值
printf("ret = %d\n,ret");
if(buffer[x] == '0')//判断从脚本中取出来的数值
{
printf("Verification FAILED\n");
printf("ret = %d\n,ret");
pclose(stream);//关闭文件
kernel.TaskSleep(10000);//休眠
return ret;
}
else
{
printf("Verification Passed\n");
printf("buffer2 = %c\n",buffer[x]);
printf("ret2 = %d\n,ret");
kernel.TaskSleep(10000);
pclose(stream);
x++;
return ret;
}
}
这是对于popen函数的应用实例。
对于fgets函数,这是一点解释
原型 char * fgets(char * s, int n,FILE *stream);
参数:
s: 字符型指针,指向存储读入数据的缓冲区的地址。
n: 从流中读入n-1个字符
stream : 指向读取的流。
返回值:
1. 当n<=0 时返回NULL,即空指针。
2. 当n=1 时,返回空串"".
3. 如果读入成功,则返回缓冲区的地址。
4. 如果读入错误或遇到文件结尾(EOF),则返回NULL.
以上是两种运行shell获取返回值的实现方法,shell很方便,需要多学习一下,有时间再发文章记录。