智一面初中级LInux运维工程师在线评测:http://www.gtalent.cn/exam/interview/eUrdXoILlsGnh6At

一、shell是什么?
从零开始编写一个minishell: 1.shell:命令行解释器 2.捕捉键盘输入:scanf,fgets,gets 3.解析输入信息-命令名称,运行参数 4.创建子进程:fork 让子进程执行对应命令名称的程序(程序替换):execvp 子进程程序替换失败必须退出,成功运行完命令程序会自己退出:exit 等待子进程退出:wait
二、minishell的实现
1.捕捉键盘输入
 

简单示例
代码如下(示例):

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 int main(int argc, char* argv[])
  6 {
  7     while(1){
  8         printf("[user@host path]$ ");
  9         fflush(stdout);
 10         char buf[1024] = {0};
 11         fgets(buf, 1023, stdin);
 12         printf("cmd:[%s]\n", buf);
 13     }
 14     return 0;
 15 }

 

简单运行结果

 完善之后:

 12         buf[strlen(buf) - 1] = '\0';
 13         int myargc = 0;
 14         char *ptr = buf, *myargv[32] = {NULL};
 15         while(*ptr != '\0'){
 16             if(*ptr != ' '){
 17                 myargv[myargc] = ptr;
 18                 myargc++;
 19                 while(*ptr != '\0' && *ptr != ' ') ptr++;
 20                 *ptr = '\0';
 21             }
 22             ptr++;
 23         }
 24         myargv[myargc] = NULL;
 25         int i = 0;
 26         for(i = 0;i < myargc;i++){
 27             printf("[%s]\n", myargv[i]);
 28         }

2.创建进程

 26         pid_t pid = fork();
 27         if(pid < 0){
 28             perror("fork error");
 29             continue;
 30         }else if(pid == 0){
 31             execvp(myargv[0], myargv);
 32             perror("execvp error");
 33             exit(-1);
 34         }
 35         wait(NULL);

 

但此时切换路径时切换不了的(cd无效), 所以此时只能调用函数改变当前的工作路径

 26         if(strcmp("cd", myargv[0]) == 0){
 27             chdir(myargv[1]);
 28             continue;
 29         }

 

3.在minishell中加上重定向功能
在我们自己实现的minishell中加入重定向功能 >> / >
1.捕捉键盘输入;
1.5解析重定向(判断有没有'>'符号)
1.6将重定向符号之前信息按照以前的命令处理方式进行处理
1.7取出重定向的文件名称
2.解析输入(得到命令名称+参数);
3.创建子进程;
3.5在程序替换之前进行标准输出重定向到指定的文件,open, dup2
4.在子进程中进行程序替换;
5.父进程进行程序等待;
重定向或者文件的信息并不会随着程序替换而消失

 20         int direct_flag = 0;//0-没有重定向,1-清空重定向,2-追加重定向
 21         char *ptr = buf;
 22         char *redirect_file = NULL;
 23         while(*ptr != '\0'){
 24             if(*ptr == '>'){
 25                 direct_flag = 1;
 26                 *ptr = '\0';
 27                 ptr++;
 28                 if(*ptr == '\0'){
 29                     direct_flag = 2;
 30                     *ptr = '\0';
 31                     ptr++;
 32                 }
 33                     while(*ptr != '\0' && *ptr == ' ') ptr++;
 34                     redirect_file = ptr;
 35                     while(*ptr != '\0' && *ptr != ' ') ptr++;
 36                     *ptr = '\0';
 37             }
 38             ptr++;
 39         }
 40         ptr = buf;

 

 62             if(direct_flag == 1){
 63                 int fd;
 64                 fd = open(redirect_file, O_CREAT|O_RDWR|O_TRUNC, 0664);
 65                 dup2(fd, 1);
 66             }else if(direct_flag == 2){
 67                 int fd;
 68                 fd = open(redirect_file, O_CREAT|O_RDWR|O_APPEND, 0664);
 69                 dup2(fd, 1);
 70             }

4.整体代码

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<ctype.h>
  6 #include<fcntl.h>
  7 #include<sys/stat.h>
  8 #include<sys/wait.h>
  9 int main(int argc,char *argv[])
 10 {
 11     while(1){
 12         printf("[user@host path]$ ");
 13         fflush(stdout);//手动刷新缓冲区
 14         char buf[1024] = {0};
 15         fgets(buf, 1023, stdin);
 16         buf[strlen(buf) - 1] = '\0';
 17 
 18 
 19 
 20         int direct_flag = 0;//0-没有重定向,1-清空重定向,2-追加重定向
 21         char *ptr = buf;
 22         char *redirect_file = NULL;
 23         while(*ptr != '\0'){
 24             if(*ptr == '>'){
 25                 direct_flag = 1;
 26                 *ptr = '\0';
 27                 ptr++;
 28                 if(*ptr == '\0'){
 29                     direct_flag = 2;
 30                     *ptr = '\0';
 31                     ptr++;
 32                 }
 33                     while(*ptr != '\0' && *ptr == ' ') ptr++;
 34                     redirect_file = ptr;
 35                     while(*ptr != '\0' && *ptr != ' ') ptr++;
 36                     *ptr = '\0';
 37             }
 38             ptr++;
 39         }
 40         ptr = buf;
 41         char *myargv[32] = {NULL};
 42         int myargc = 0;
 43         while(*ptr != '\0'){
 44             if(*ptr != ' '){
 45                 myargv[myargc] = ptr;
 46                 myargc++;
 47                 while(*ptr != '\0' && *ptr != ' ') ptr++;
 48                 *ptr = '\0';
 49             }
 50             ptr++;
 51         }
 52         myargv[myargc] = NULL;
 53         if(strcmp("cd", myargv[0]) == 0){
 54             chdir(myargv[1]);
 55             continue;
 56         }
 57         pid_t pid = fork();
 58         if(pid < 0){
 59             perror("fork error");
 60             continue;
 61         }else if(pid == 0){
 62             if(direct_flag == 1){
 63                 int fd;
 64                 fd = open(redirect_file, O_CREAT|O_RDWR|O_TRUNC, 0664);
 65                 dup2(fd, 1);
 66             }else if(direct_flag == 2){
 67                 int fd;
 68                 fd = open(redirect_file, O_CREAT|O_RDWR|O_APPEND, 0664);
 69                 dup2(fd, 1);
 70             }
 71             execvp(myargv[0],myargv);
 72             perror("execvp error");
 73             exit(-1);
 74         }
 75         wait(NULL);
 76     }
 77     return 0;
 78 }


运维工程师QQ在线交流群:580175957