中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > 综合其它
用重定向原理实现远程执行交互
作者:未知 时间:2005-07-27 23:27 出处:CSDN 责编:chinaitpower
              摘要:用重定向原理实现远程执行交互

用重定向原理实现远程执行交互

这是一个简单工具,用于远程执行在服务器上的脚本或进程。
原理是在服务器上将socket重定向到所运行的进程的标准输入输出流,这样进程的标准输出(STDOUT)会自动发送到客户端,客户端写到socket上的数据自动输出到进程的标准输入(STDIN),这样就实现了远程交互,类似telnet服务.
代码如下:

//句柄复制  from qmail tcpserver
int fd_copy(int to,int from)

{
  if (to == from) return 0;
  if (fcntl(from,F_GETFL,0) == -1) return -1;
  close(to);
  if (fcntl(from,F_DUPFD,to) == -1) return -1;
  return 0;
}
//句柄复制,并关闭源句柄 from from qmail tcpserver
int fd_move(int to,int from)
{
  if (to == from) return 0;
  if (fd_copy(to,from) == -1) return -1;
  close(from);
  return 0;
}


//处理客户端连接的主循环
void       clientloop(CONNECT_INFO *pConn)

{
   int pid ;
   int stat = 0;
   int res = 0;
   char cmd[100]="";
   char Prompt[]="->"; //定义提示符
   int i;
   SendData(pConn->socket,Prompt,strlen(Prompt)); //输出提示符
    while(1) //主循环
    {
      memset(cmd,0,sizeof(cmd));
       if(RecvData(pConn->socket,cmd,sizeof(cmd),1000 )>0)  //从socket上获取指令(主进程)
     {
      chomp(cmd); //去掉回车换行,TAB,空格
      printf("Get cmd:[%s]\n",cmd);  //在服务器端打印出收到的命令
      if(strcmp(cmd,"quit")==0) //收到quit则退出
      {      break;   }
      pid = fork();  //创建子进程  
        if(pid < 0)          //错误
          {
        perror("fork error");
        break;
       }
        if(pid > 0) //主进程
        {
         waitpid(pid,&stat,WCONTINUED); //等待子进程退出
         kill(pid,9);                                            //再kill一次防止僵死进程
            SendData(pConn->socket,Prompt,strlen(Prompt)); //发送提示符号
        }else{
           fd_copy(0,pConn->socket);         //将socket重定向到标准输入
           fd_move(1,pConn->socket);       //将标准输出重定向到socket
           printf("[%d]run cmd %s\n",getpid(),cmd);   //打印当前命令
        res =  execl(cmd,"",(char*)0);          //使用execl运行指令,子进程被指令创建的进程取代,该进程的输入输出已经被重定向
        if (errno == ENOEXEC)                     //这是处理某些没有指定默认shell的脚本
                   execl ("/bin/sh", "sh", "-c", cmd, (char *)0);
                               else
          printf("run res = %d,%s\n",res,strerror(errno));  //错误输出到客户端
              exit(0);
        }//pid
      }//recvdata
    }//while
}

//主程序入口
main(){

   /*建立监听socket,获得客户端连接,对新连接fork进程,调用clientloop*/

}

目前这个代码还比较粗糙,能实现基本的运行和交互,最需要优化的主要是execl的调用方法,这样的写法只能输入完整路径名,而且不能带参数。可以

1:根据当前的PATH环境变量,实现类似whereis功能,

2:对输入的命令行进行解析,获取命令参数,构造成char **字符数组传递给execl.

还有一种方式是用popen,用popen的效果也满不错,比起用execl来,避免了以上1,2问题,还可以对输出的信息先进行处理再发给客户端

int runcmdpipe(const char *sCmd)
{
 char pline [1024];
 FILE *fp = NULL;
    if ((fp = popen (sCmd, "r")) == NULL)
                return -1;
   while (fgets (pline, sizeof(pline)-1, fp)!= NULL)
   {
           printf(">> %s",pline); //输出到客户端
   }
   pclose (fp);
   return ncount;
}

客户端可以用telnet程序,但unix和windows的telnet客户端有小小差异,unix的telnet输入回车才发送,而windows的telnet一击键即刻发送,所以程序应该判断是否得到回车换行,才认为是一个完整的指令。

还有一些unix命令如su,top,vi在这种模式下运行不太顺畅,但此工具已经满足要求了,以后有空再研究如何解决。


关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有