在集群上跑程序的人都知道要编辑一个节点列表文件来说明在哪些机器上启动进程,以及在某个机器上启动的进程的数量,最典型的情况是mpi。但是如果机器的数量过大,比如有500个节点的机群,这样要维护这个文件也是一件比较头疼的事情。

    维护节点列表文件,主要是进行三个操作:创建列表,删除某些节点,修改某些节点。接下来就可以用C或者Python实现一个具备这三种功能的小程序了。今天上午实现了一个,代码贴在这里。

   

  1. /**************************************************************************************************************************  
  2. * Name: md                                                                                                                *  
  3. * Author: Chaos Lee                                                                                                       *  
  4. * Date: 2012-06-07                                                                                                        *  
  5. * Description: This program is used to create and edit a host file. It provides three simple functions to accomplish this.*  
  6. *              (1) To create a host file: mh -p prefix_name -f file_name -l num1-num2 num3 num4-num5                      *  
  7. *                  Above command will create a host file whose name is file_name,containing a machine name list in format *  
  8. *                  as bellow:                                                                                             *  
  9. *                  prefix_namenum1                                            *  
  10. *                  ...                                                                                                    *  
  11. *                  prefix_namenum2                                                                                        *  
  12. *                  prefix_namenum3                                                                                        *  
  13. *                  prefix_namenum4                                                                                        *  
  14. *                  ...                                                                                                    *  
  15. *                  prefix_namenum5                                                                                        *  
  16. *              (2) To delete some machine names from the host file: mh -f file_name -d num1-num2 num3 num4-num5.          *  
  17. *                  Above command will delete prefix_namenum1,...,prefix_namenume2,prefix_namenum3,prefix_namenum4,...     *  
  18. *                  ,prefix_namenum5 from the file indicated by the file_name                                              *  
  19. *              (3) To modify some machine names from the host file: mh -f file_name -m num1 num2 num3 num4                *    
  20. *                  Above command will change prefix_namenum1 to prefix_namenum2,prefix_namenum3 to prefix_namenum4.       *  
  21. **************************************************************************************************************************/ 
  22. #include<stdio.h>  
  23. #include<string.h>  
  24. #include<ctype.h>  
  25. #include<stdlib.h>  
  26.  
  27. typedef enum com_type_tag {create,delete,modify} com_type;  
  28. typedef int status;  
  29.  
  30. #define false 0  
  31. #define true 1  
  32. #define EXIT_SUCCESS 0  
  33. #define BAD_FORMAT  -1  
  34. #define MAX_NODE_NUMBER 999  
  35. char machine_names[MAX_NODE_NUMBER][20];  
  36. int names_number = 0;  
  37. #define XXXX  do{\  
  38.         printf("FILE:%s LINE:%d\n",__FILE__,__LINE__); \  
  39.         fflush(stdout); \  
  40.         }while(0);  
  41. int find_minus(char *nums)  
  42. {     
  43.     int len = strlen(nums);  
  44.     int i;  
  45.     for(i=0;i<len;i++)  
  46.     {  
  47.         if(nums[i]=='-')  
  48.         {  
  49.             return i;  
  50.         }  
  51.     }  
  52.     return -1;  
  53. }  
  54. status check_cd_num(char * nums)  
  55. {  
  56.     int minus_pos = find_minus(nums);  
  57.     int i = 0;  
  58.     if(-1 == minus_pos)  
  59.         return check_m_num(nums);  
  60.     nums[minus_pos] = '\0';  
  61.     if(false == check_m_num(nums) || false == check_m_num(nums+i+1) )  
  62.         return false;  
  63.     nums[minus_pos] = '-';  
  64.     return true;  
  65. }  
  66.  
  67. status check_m_num(char * num)  
  68. {  
  69.     int i=0;  
  70.     int len = strlen(num);  
  71.     if(len>3 || len==0)  
  72.         return false;  
  73.     for(i=0;i<len;i++)  
  74.     {  
  75.         if( !isdigit(num[i]) )  
  76.             return false;  
  77.     }  
  78.     return true;  
  79. }  
  80.  
  81. status check_num_list(int type,int argc,char *argv[])  
  82. {  
  83.     int i;  
  84.     int start=4;  
  85.     if(type == create || type == delete)  
  86.     {  
  87.         if(type == create)  
  88.             start = 6;  
  89.         for(i=start;i<argc;i++)  
  90.         {  
  91.             status res = check_cd_num(argv[i]);  
  92.             if(!res)  
  93.                 return res;  
  94.         }  
  95.     }  
  96.     else if(type == modify)  
  97.     {  
  98.         int counter = 0;  
  99.         for(i=start;i<argc;i++)  
  100.         {  
  101.             status res = check_m_num(argv[i]);  
  102.             if(!res)  
  103.                 return res;  
  104.             counter++;  
  105.         }  
  106.         if(counter & 1)  
  107.             return false;  
  108.     }  
  109.     else 
  110.     {  
  111.         printf("command type is wrong.\n");  
  112.         return false;  
  113.     }  
  114.     return true;  
  115. }  
  116.  
  117. com_type analyze_command(int argc,char *argv[])  
  118. {  
  119.     int i=0;  
  120.     com_type type;  
  121.     if( 0 == strcmp(argv[1],"-p") && 0 == strcmp(argv[3],"-f") && 0 == strcmp(argv[5],"-l") )  
  122.         type = create;  
  123.     else if(0 == strcmp(argv[1],"-f")  && 0 == strcmp(argv[3],"-d") )  
  124.         type = delete;  
  125.     else if(0 == strcmp(argv[1],"-f") && 0 == strcmp(argv[3],"-m"))  
  126.         type = modify;  
  127.     else 
  128.     {  
  129.         printf("command in bad format.\n");  
  130.         exit(BAD_FORMAT);  
  131.     }  
  132.     if(false == check_num_list(type,argc,argv))  
  133.     {  
  134.         printf("number list in bad format\n");  
  135.         exit(BAD_FORMAT);  
  136.     }  
  137.     return type;  
  138. }  
  139. void get_range(char *nums,int * num_min,int * num_max)  
  140. {  
  141.     int minus_pos = find_minus(nums);  
  142.     if( -1 == minus_pos )  
  143.         *num_min = *num_max = atoi(nums);  
  144.     else 
  145.     {  
  146.         *num_min = atoi(nums);  
  147.         *num_max = atoi(nums+minus_pos+1);  
  148.     }  
  149. }  
  150. status create_list(int argc,char *argv[])  
  151. {  
  152.     int i,num_min,num_max,j;  
  153.     FILE * fp;  
  154.     //printf("filename = %s\n",argv[4]);  
  155.     fp  = fopen(argv[4],"w");  
  156.     if(NULL == fp)  
  157.     {  
  158.         printf("creating file %s error.\n",argv[4]);  
  159.         return false;  
  160.     }  
  161.     for(i = 6;i<argc;i++)  
  162.     {  
  163.         get_range(argv[i],&num_min,&num_max);  
  164.         //printf("num_min=%d num_max=%d\n",num_min,num_max);  
  165.         for(j=num_min;j<=num_max;j++)  
  166.             sprintf(machine_names[names_number++],"%s%03d",argv[2],j);    
  167.     }  
  168.     for(i=0;i<names_number;i++)  
  169.     {  
  170.         fprintf(fp,"%s\n",machine_names[i]);  
  171.     }  
  172.     fclose(fp);  
  173.     return true;  
  174. }  
  175. status delete_list(int argc,char *argv[])  
  176. {  
  177.     status delete_flag_array[MAX_NODE_NUMBER];  
  178.     int i,num_min,num_max,j;  
  179.     FILE * fp;  
  180.     int minus_pos,id;  
  181.     char prefix[20];  
  182.     for(i = 0;i<MAX_NODE_NUMBER;i++)  
  183.         delete_flag_array[i] = false;  
  184.     for(i = 4;i<argc;i++)  
  185.     {  
  186.         get_range(argv[i],&num_min,&num_max);  
  187.         for(j=num_min;j<=num_max;j++)  
  188.             delete_flag_array[j] = true;          
  189.     }  
  190.     fp = fopen(argv[2],"r");  
  191.     if(NULL == fp)  
  192.     {  
  193.         printf("opening file %s error.\n",argv[2]);  
  194.         return false;  
  195.     }  
  196.     while(!feof(fp))  
  197.     {  
  198.         fscanf(fp,"%s",machine_names[names_number++]);  
  199.         if(strcmp("",machine_names[names_number])!=0)  
  200.             names_number++;  
  201.     }  
  202.     fclose(fp);  
  203.     fp = fopen(argv[2],"w");  
  204.     if(NULL == fp)  
  205.     {  
  206.         printf("recreating file %s error.\n",argv[2]);  
  207.         return false;  
  208.     }  
  209.     if(0 == names_number)  
  210.         return false;  
  211.     minus_pos = find_minus(machine_names[0]);  
  212.     if(-1 == minus_pos)  
  213.         return false;  
  214.     for(i=0;i<names_number;i++)  
  215.     {  
  216.         id = atoi(machine_names[i]+minus_pos+1);  
  217.         if(0 == id)  
  218.             continue;  
  219.         if(true != delete_flag_array[id])  
  220.         {  
  221.             fprintf(fp,"%s\n",machine_names[i]);  
  222.         }  
  223.     }  
  224.     fclose(fp);  
  225.     return true;  
  226. }  
  227. status modify_list(int argc,char *argv[])  
  228. {  
  229.     int id_map[MAX_NODE_NUMBER],i=0;  
  230.     FILE *fp;  
  231.     int minus_pos,id;  
  232.     char prefix[20];  
  233.     for(i=0;i<MAX_NODE_NUMBER;i++)  
  234.     {  
  235.         id_map[i] = -1;  
  236.     }  
  237.     i=4;  
  238.     while(i<argc)  
  239.     {  
  240.         id_map[atoi(argv[i])] = atoi(argv[i+1]);  
  241.         i+=2;  
  242.     }  
  243.     fp = fopen(argv[2],"r");  
  244.     if(NULL == fp)  
  245.     {  
  246.         printf("opening file %s error.\n",argv[2]);  
  247.         return false;  
  248.     }  
  249.     while(!feof(fp))  
  250.     {  
  251.         fscanf(fp,"%s",machine_names[names_number]);  
  252.         if(strcmp("",machine_names[names_number])!=0)  
  253.             names_number++;  
  254.     }  
  255.     fclose(fp);  
  256.     fp = fopen(argv[2],"w");  
  257.     if(NULL == fp)  
  258.     {  
  259.         printf("recreating file %s error.\n",argv[2]);  
  260.         return false;  
  261.     }  
  262.     if(0 == names_number)  
  263.         return false;  
  264.     minus_pos = find_minus(machine_names[0]);  
  265.     if(-1 == minus_pos)  
  266.         return false;  
  267.     strncpy(prefix,machine_names[0],minus_pos+1);  
  268.     for(i=0;i<names_number;i++)  
  269.     {  
  270.         id = atoi(machine_names[i]+minus_pos+1);  
  271.         if(0 == id)  
  272.             continue;  
  273.         if(-1 != id_map[id])  
  274.         {  
  275.             fprintf(fp,"%s%03d\n",prefix,id_map[id]);  
  276.         }  
  277.         else 
  278.         {  
  279.             fprintf(fp,"%s\n",machine_names[i]);  
  280.         }  
  281.     }  
  282.     fclose(fp);  
  283.     return true;  
  284. }     
  285. int main(int argc,char *argv[])  
  286. {  
  287.     com_type type;  
  288.     status res;  
  289.     type = analyze_command(argc,argv);  
  290.     switch(type)  
  291.     {  
  292.         case create:  
  293.             res = create_list(argc,argv);  
  294.             if(false == res)  
  295.             {  
  296.                 printf("creating list error.\n");  
  297.                 exit(EXIT_FAILURE);  
  298.             }  
  299.               
  300.             break;  
  301.         case delete:  
  302.             res = delete_list(argc,argv);  
  303.             if(false == res)  
  304.             {  
  305.                 printf("deleting list error.\n");  
  306.                 exit(EXIT_FAILURE);  
  307.             }  
  308.             break;  
  309.         case modify:  
  310.             res = modify_list(argc,argv);  
  311.             if(false == res)  
  312.             {  
  313.                 printf("modifying list error.\n");  
  314.                 exit(EXIT_FAILURE);  
  315.             }  
  316.             break;  
  317.         default:  
  318.             printf("Panic:type error.\n");  
  319.             exit(BAD_FORMAT);  
  320.     }     
  321.     return EXIT_SUCCESS;  
  322. }  
  323.