zoukankan      html  css  js  c++  java
  • linux执行命令并获取结果(system)

    执行系统命令,并返回输出的结果

    首先需要了解mkstemp():

    mkstemp()函数在系统中以唯一的文件名创建一个文件并打开,而且只有当前用户才能访问这个临时文件,并进行读、写操作。
      mkstemp函数在系统中以唯一的文件名创建一个文件并打开,而且只有当前用户才能访问这个临时文件,并进行读、写操作。 mkstemp函数只有一个参数,这个参数是个以“XXXXXX”结尾的非空字符串。mkstemp函数会用随机产生的字符串替换“XXXXXX”,保证 了文件名的唯一性。 函数返回一个文件描述符,如果执行失败返回-1。
      在glibc 2.0.6 以及更早的glibc库中这个文件的访问权限是0666,glibc 2.0.7以后的库这个文件的访问权限是0600。
      临时文件使用完成后应及时删除,否则临时文件目录会塞满垃圾。由于mkstemp函数创建的临时文件不能自动删除,所以执行完 mkstemp函数后要调用unlink函数,unlink函数删除文件的目录入口,但临时文件还可以通过文件描述符进行访问,直到最后一个打开的进程关 闭文件操作符,或者程序退出后临时文件被自动彻底地删除。
     
    函数功能表示:读取命令执行结果,放到临时文件,并将结果读到buf中,删除临时文件
     
    /**
     *@brief          执行系统命令,并返回输出的结果
     *@param[in]      cmdstring,命令串
     *@param[in]      buf,存放命令结果的缓冲区
     *@param[in]      size,缓冲区的大小
     *@param[out]     
     *@return         返回写入到buf中的字符串长度,不含 ; -1: 失败;
     *@remark         
     *@version        V1.0.0
     *@note     	  buf中最多返回size-1个字符,字符串始终以结尾。
    */
    int get_cmd_results(const char *cmdstring, char *buff, int size)
    {
    	char cmd_string[200] = {0};
    	char tmpfile[100] = {0};
    	char tmp_buf[100] = {0};
    	int fd;
    	int tmp_fd;
    	int nbytes;
    
          memset(buff, 0, size);
    
    	if((cmdstring == NULL) ||
    		(strlen(cmdstring) > (sizeof(tmpfile) + 8)) ||
    		((strlen(cmdstring) + strlen(tmpfile) + 5) > sizeof(cmd_string)))
    	{
            printf("cmd is too long or NULL!
    ");
            return -1;
    	}
    	sscanf(cmdstring, "%[a-Z]", tmp_buf);/*%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配) */
    	sprintf(tmpfile, "/tmp/%s-XXXXXX", tmp_buf);
    
    	tmp_fd = mkstemp(tmpfile);
    	if(tmp_fd < 0)
        {
    		printf("mkstemp failed
    ");
    		return -1;
    	}
    	close(tmp_fd);
    
    	sprintf(cmd_string, "%s > %s 2>&1", cmdstring, tmpfile);/*标准输出(1),标准错误(2)都输出到临时文件*/
    	if(system_ex(cmd_string, 20) < 0)
        {
    		printf("run "%s" ret < 0!
    ", cmd_string);
    	}
    
    	fd = open(tmpfile, O_RDONLY);
    	if(fd < 0)
        {
    		printf("open %s failed!
    ", tmpfile);
    		nbytes = -1;
    	}
    	else
    	{
    		nbytes = read(fd, buff, size - 1);
    		close(fd);
    	}
    
    	memset(cmd_string, 0, sizeof(cmd_string));
    	sprintf(cmd_string, "rm -rf /tmp/%s-*", tmp_buf);
    	system_ex(cmd_string, 20);
    
    	return nbytes;
    }
    

      system_ex:

    首先请了解信号:signal和sigaction

    https://blog.csdn.net/weibo1230123/article/details/81411827

    https://www.cnblogs.com/lidabo/p/4581065.html

    创建子进程执行命令,父进程忽略ignore SIGINT and SIGQUIT ,来避免影响子进程执行即需要子进程执行完毕,子进程不忽略信号,当超时或者子进程退出

    则恢复信号状态,超时的话,还需要kill掉子进程等

    //system函数扩展,加入超时值(0表示永久等待)
    //超时时返回-2,其他情况返回不变。
    int system_ex(const char *cmdstring, unsigned int timeout)   /* with appropriate signal handling */
    {
    	pid_t               pid;
    	int                 status;
    	struct sigaction    ignore, saveintr, savequit;
    	sigset_t            chldmask, savemask;
    
    	//精度换成十分之一秒
    	timeout *= 10;
    	if (timeout == 0)
    		timeout = 0xFFFFFFFF;
    
    	if (cmdstring == NULL)
    		return(1);      /* always a command processor with UNIX */
    
    	ignore.sa_handler = SIG_IGN;    /* ignore SIGINT and SIGQUIT */
    	sigemptyset(&ignore.sa_mask);
    	ignore.sa_flags = 0;
    	if (sigaction(SIGINT, &ignore, &saveintr) < 0)
    		return(-1);
    	if (sigaction(SIGQUIT, &ignore, &savequit) < 0)
    		return(-1);
    	sigemptyset(&chldmask);         /* now block SIGCHLD */
    	sigaddset(&chldmask, SIGCHLD);
    	if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0)
    		return(-1);
    
    	if ((pid = fork()) < 0) {
    		return -1;    /* probably out of processes */
    	} else if (pid == 0) {          /* child */
    		/* restore previous signal actions & reset signal mask */
    		sigaction(SIGINT, &saveintr, NULL);
    		sigaction(SIGQUIT, &savequit, NULL);
    		sigprocmask(SIG_SETMASK, &savemask, NULL);
    /*通常exec会放在fork() 函数的子进程部分, 来替代子进程执行啦, 执行成功后子程序就会消失,  但是执行失败的话, 必须用exit()函数来让子进程退出!*/
    		execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);/*exec函数会取代执行它的进程,  也就是说, 一旦exec函数执行成功, 它就不会返回了, 进程结束.   但是如果exec函数执行失败, 它会返回失败的信息,  而且进程继续执行后面的代码!*/
    		_exit(127);     /* exec error */
    	}
    
    	/* parent */
    	int ret = 0;
    	while (timeout-- > 0 &&
    		(ret = waitpid(pid, &status, WNOHANG)) == 0)
    		usleep(100*1000);
    
    	/* restore previous signal actions & reset signal mask */
    	if (sigaction(SIGINT, &saveintr, NULL) < 0)
    		return(-1);
    	if (sigaction(SIGQUIT, &savequit, NULL) < 0)
    		return(-1);
    	if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0)
    		return(-1);
    
    	if (ret < 0)
    		return -1;
    
    	if (ret > 0)
    		return status;
    
    	kill(pid, SIGKILL);
    	waitpid(pid, &status, 0);
    	return -2;
    }
    

      

  • 相关阅读:
    Codeforces Round #251 (Div. 2) A
    topcoder SRM 623 DIV2 CatAndRat
    topcoder SRM 623 DIV2 CatchTheBeatEasy
    topcoder SRM 622 DIV2 FibonacciDiv2
    topcoder SRM 622 DIV2 BoxesDiv2
    Leetcode Linked List Cycle II
    leetcode Linked List Cycle
    Leetcode Search Insert Position
    关于vim插件
    Codeforces Round #248 (Div. 2) B. Kuriyama Mirai's Stones
  • 原文地址:https://www.cnblogs.com/bwbfight/p/10682722.html
Copyright © 2011-2022 走看看