C++ code中调用perl/shll脚本方法
来源:互联网 发布:java多人聊天室源代码 编辑:程序博客网 时间:2024/05/21 01:45
在C++里,如果想要执行某个脚本或者命令,有三种方法:
一、调用系统函数system().
intsystem(const char *string),所在头文件:#include<stdlib.h>
函数说明:system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD信号会被暂时搁置,SIGINT和SIGQUIT信号则会被忽略。
参数说明:string,可以为对应的shell、perl脚本的字符串。
返回值:=-1:出现错误|=0:调用成功但是没有出现子进程|>0:成功退出的子进程的id
如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno来确认执行成功。
注:在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题,
EG1:if(system(NULL)) puts("system execute OK!");
else exit(-1);
int errcode =system(cmd.c_str());
if (errno ==EAGAIN)
INFO(NBI_STR("the error is EAGAIN."));
else if (errno== EINTR)
INFO(NBI_STR("the error is EINTR"));
else if (errno== ENOMEM)
INFO(NBI_STR("the error is ENOMEM"));
elseINFO(NBI_STR("the error is undefined"));
EG2:#include<stdlib.h>
main()
{system(“ls -al /etc/passwd/etc/shadow”);}
执行结果:
-rw-r--r-- 1 root root 705 Sep 3 13:52 /etc/passwd
-r--------- 1 root root 572 Sep 2 15:34 /etc/shadow
二、调用创建子进程函数fork() 并执行execl()
example:
pid_tpid = fork();
if(pid < 0)
Cout<<"forkfailed! errno :"<< errno<<endl;
else if(pid == 0)
{ cout<<"fork success "<<endl;
if(execl("/bin/sh","sh", "-c", “pwd”, NULL) < 0)
{
Cout<<”executefail,errno:"<<errno<<endl;
exit(-1);
}
}
int termstat;
while(waitpid(pid,&termstat,0) != pid)
{
if(errno !=EINTR)
{
Cout<<”waitpidfailed!errno"<<errno<<endl;
break;
}
}
这里主要有三个函数fork()/execl()/waitpid().
pid_t fork( void): 所在头文件:#include<unistd.h>
函数说明:该函数在现有进程中创建一个新的进程,即子进程,它被调用一次,但返回两次。即子进程中返回值为0,父进程中返回子进程ID.子进程是父进程的副本,将获得父进程的数据空间、堆、栈等资源的副本。即父子进程之间不共享这些存储空间。不同的系统下,父子进程的运行顺序是不相同的。故而在代码中不能对此作出任何假设。故而我们可以通过该函数的返回值来判定是父进程还是子进程,并在父子进程中分别实现不同的动作。在该例子中,子进程调用execl函数执行相应的shell脚本,父进程调用waitpid()等待子进程执行完。当父进程稍后的处理内容有赖于子进程执行完后的结果,需要调用waitpid等待子进程完成。
返回值:在子进程中返回0,在父进程中返回子进程的id.
错误信息:创建子进程出错时有如下错误信息:
EAGAIN:达到进程数上限
ENOMEM:没有足够空间给一个新进程分配。
注:pid_t是一个宏定义,其实质是int,被定义在#include<sys/types.h>中。
intexecl(const char *path, const char *arg[0], *arg[1] ...,NULL)所在头文件:#include<unistd.h>
函数说明:该函数是exec函数族中的一个,另有函数:execle,execlp, execv, execve, execvp。该族函数主要作用为,执行参数中的命令或者是其他程序、脚本,函数名里含l(list)表示参数列表,v
参数说明:path-指向要执行的文件路径. argv[0],argv[1]...-执行该文件时传递的参数列表,最后一个参数须用空指针NULL/(char*)0作结束。
返回值:执行成功则返回不返回值,失败则返回-1,失败原因存于errno中,可通过perror打印出对应的错误信息。
Example:#include <unistd.h>
int main()
{
// 执行/bin目录下的ls, 第一参数为程序名ls,第二个参数为"-al", 第三个参数"/etc/"
Int state = execl("/bin/ls","ls","-al","/etc/",NULL);
If(state<0)
{perror(“execute fail!”); return -1;}
return 0;
}
注:这里如果命令:ls –al /etc/执行不成功,那么将报错(executefail: $errno),即perror()输出的内容为其参数内容再加上全局变量errno中对应的内容。
pid_twaitpid(pid_t pid,int * status,int options) 所在的头文件:#include<sys/wait.h>
函数说明:该函数可暂时停止目前进程的执行,直到有信号来到或子进程。
参数说明:status-子进程的结束状态值。如果不在意结束状态值,则参数 status 可设为 NULL。
pid -欲等待的子进程识别码.其对应的含义如下:
pid<-1等待进程组识别码为 pid绝对值的任何子进程。
pid=-1 等待任何子进程,相当于 wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为 pid的子进程。
Options-控制waitpid()的一些额外选项。可以为 0或用"|"运算符联接起来的选项。选项包括:
0:若调用该函数时pid指定的子进程没有结束,则等待,直到子进程结束,返回子进程的pid.
WNOHANG:若子进程没有结束,则不等待,而是直接返回0,若结束,则返回子进程的ID。
WUNTRACED:若子进程进入暂停(STOP)状态,则马上返回,但子进程的结束状态不予以理会。
WCONTINUED:若子进程进入继续(CONTINUE)状态,函数马上返回,父进程被唤醒。
返回值:子进程的ID、0或者是负数,代表pid不对。
注:子进程的结束状态将置于status中,一般子进程退出的方式有:1)通过exit()退出。2)信号导致退出,如段错误信号SIGSEGV、非法指令信号SIGILL、管道断裂信号SIGPIPE、程序流产信号SIGABORT,对于这些退出原因,父进程需要知道其原因。以上两种退出方式均会重置status状态。另外还有一种也会置status状态的情况,即:子进程的状态发生变化时,一般为进程转换为STOPPED或者CONTINUED状态时,默认状态下父进程会收到这些状态信号,但不会在这两个状态下被唤醒。只有设置了waitpid()中参数option的值时才有可能唤醒父进程。若父进程想屏蔽掉这两个信号,不接收它们,那么只需要在注册SIGCHLD时设置SA_NOCLDSTOP,来拒绝进程变化时接收信号的行为。系统中对status的状态作了一些宏定义,具体有:
WIFEXITED(status)若子进程正常结束时,为真;对于这种情况可执行WEXITSTATUS(status),取子进程传给exit或_eixt的低8位
WEXITSTATUS(status)取得子进程 exit()返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)若子进程因信号而异常结束,则为真;对于这种情况可执行WTERMSIG(status),取得子进程结束的信号编号。
WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED来判断后才使用此宏。
WIFSTOPPED(status) 若子进程当前为暂停状态时,则该量为真;对于这种情况可执行WSTOPSIG(status),取得子进程暂停的信号编号。
WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。
三、 利用封装的popen()
Example:char line[MAXLINE];
memset(line, '\0', MAXLINE);
FILE *fpout;
if ((fpout = popen(cmd.c_str(), "r")) !=NULL)
{Cout<<”command execution!!! "<<endl;
while(fgets(line, 233, fpout) != NULL)
{Cout<<line<<endl; }
int res =pclose(fpout);
if (res== -1) {
switch(errno)
{case EMFILE: cout<<"the error is:EMFILE."<<endl;
case ECHILD: cout<<”the error is ECHILD."<<endl;
case EINVAL: cout<<”theparameter type is not legal."<<endl;
default: cout<<errno<<endl;}
}
else {cout<<”popenfail”<<endl;
return -1;}
这里主要有三个函数popen()/fgets()/pclose()
FILE
* popen
(const
char
*command,const
char
*type)
int pclose (FILE *stream );
所在头文件
#include<stdio.h>
函数说明:popen()函数通过创建一个管道,调用fork 产生一个子进程,执行一个 shell以运行命令来开启一个进程. 此进程必须由pclose()函数关闭。该函数类似于封装了第二种方法。
pclose() 函数关闭标准 I/O流,等待命令执行结束,然后返回 shell 的终止状态。如果 shell不能被执行,则pclose() 返回的终止状态与 shell已执行 exit 一样。
参数说明:
command:指向以 NULL结束的 shell 命令字符串的指针,这行命令将被传到 bin/sh 并使用-c标志,shell 将执行这个命令。Type:读(“r”)或者写(“w”)中的一种.若为“r”则返回的文件指针连接到执行command后的标准输出。若为“w”则返回的文件指针连接到command的标准输入。stream:由popen()创建的file stream.
返回值:popen()若调用fork()或pipe()失败,或不能分配内存,则将返回NULL。否则返回标准I/O流。
pclose():返回系统调用wait4()的状态。若stream无效或系统调用wait4()失败,则返回-1.
返回错误类型:若分配内存失败,则设置errno;若调用fork()或pipe()失败,则errno将被置为与这两个函数调用失败时相应的错误类型;若参数type不合法,errno将返回EINVAL。
char*fgets(char *buf, int bufsize, FILE *stream) 所在头文件:
函数说明:该函数从文件结构体指针stream中读取数据,每次读取一行,读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符,如果文件中的该行,不足bufsize个字符,则读完该行就结束。函数成功将返回buf,失败或读到文件结尾返回NULL。因读到结尾时也返回NULL,故而不可通过返回值判断函数执行是否成功。而应借助feof()或ferror()来判断。
参数说明: *buf: 字符型指针,指向用来存储所得数据的地址。
bufsize:整型数据,指明buf指向的字符数组的大小。
*stream:文件结构体指针,将要读取的文件流。
返回值:若bufsize< =0,则返回NULL,若bufsize ==1,则返回“”,即一个空串。若成功,则返回string,即字符串的首地址。若出错,或读到结尾,则返回NULL。
- C++ code中调用perl/shll脚本方法
- JAVA中调用perl脚本!
- perl中调用方法
- perl调用c语言方法
- 在windows平台下在C语言中调用perl脚本
- C#调用Perl脚本
- c++ 调用 perl 脚本
- python调用perl脚本
- C中调用shell 脚本
- perl脚本调试方法
- JAVA程序调用Perl脚本
- Perl 脚本中单元测试
- Shell向Perl脚本中传递变量的方法
- Shell向Perl脚本中传递变量的方法
- C调用shell script脚本的方法
- Lua脚本:Lua调用C实现方法
- Lua脚本:C调用Lua实现方法
- LUA脚本调用C函数的方法
- 时光飞逝
- php免费短信
- 关于unsigned char、unsigned short使用printf(“%d”)进行输出的结果
- Hash
- php支付系统
- C++ code中调用perl/shll脚本方法
- C语言基础2
- EF架构之二
- 2015年5月信息系统项目管理师通过率
- Android Studio中使用Gradle打包
- webdriver实现原理
- EF架构之一
- 看opengl写代码(7) 使用混合数组(glInterLeavedArrays)
- Selenium源码分析之WebDriver