一个月,学了很多东西,遇到很多问题,觉得自己很白菜,总归每天在进步,总结下

大概做了三件事:

  1. 设计实现商城道具管理系统,数据库(mysql)+后端(python,flask)+前端(js,html,css)
  2. 实现一个脚本解释器,c语言编程
  3. 实现一个运维脚本,shell编程

操作系统debian,连接远程服务器开发putty

 

  • 商城道具管理系统

_mini.py  (control层)

_view.py (view层)

_dao.py (model层)

_template (html)

_static (图片,js,css)

  • 脚本解释器

类似bash

#define TRUE 1
#define max_name 256
#define max_path 1024
#define max_prompt 1024
#define MAXLINE 4096
#define MAXARG 20
#define MAXPIDTABLE 1024
#define BACKGROUND 1
#define IN_REDIRECT 2
#define OUT_REDIRECT 4
#define OUT_REDIRECT_APPEND 8
#define IS_PIPED 16
#define MAX_TYPE_PROMPT 20
#ifdef READLINE_ON
#include <readline/readline.h>
#include <readline/history.h>
#endif
#include <unistd.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>

struct parse_info 
{
    int flag;
    char* in_file;
    char* out_file;
    char* command2;
    char** parameters2;
};


char *buffer;
pid_t BPTable[MAXPIDTABLE];
struct passwd *pwd;

//显示个性化的命令行提示符
void display(char *prompt){
    pwd=getpwuid(getuid());//get recent uid
    char hostname[max_name];
    char pathname[max_path];
    int len;
    getcwd(pathname,max_path);//get recent pathname

    if(gethostname(hostname,max_name)==0)//get hostname
        sprintf(prompt,"[qjjshell]%s@%s:",pwd->pw_name,hostname);
    else
        sprintf(prompt,"[qjjshell]%s@unknown:",pwd->pw_name);

    len = strlen(prompt);
    if(strlen(pathname) < strlen(pwd->pw_dir) || strncmp(pathname,pwd->pw_dir,strlen(pwd->pw_dir))!=0)//get pathname
        sprintf(prompt+len,"%s",pathname);
   
    else
        sprintf(prompt+len,"~%s",pathname+strlen(pwd->pw_dir));

    len = strlen(prompt);
    if(geteuid()==0)//get premission
        sprintf(prompt+len,"#");
    else
        sprintf(prompt+len,"$");

    return;
    
}

//读取命令行输入的命令
int readcmd(char **command,char **parameters,char *prompt){
#ifdef READLINE_ON
    free(buffer);
    buffer = readline(prompt);
    if(feof(stdin)) {
        printf("\n");
        exit(0);
    }

#else
    printf("%s",prompt);
    char* Res_fgets = fgets(buffer,MAXLINE,stdin);
    if(Res_fgets == NULL)
    {
        printf("\n");
        exit(0);
    }       
#endif

    if(buffer[0] == '\0')
        return -1;
    char *pStart,*pEnd;
    int count = 0;
    int isFinished = 0;
    pStart = pEnd = buffer;
    while(isFinished == 0)
    {
        while((*pEnd == ' ' && *pStart == ' ') || (*pEnd == '\t' && *pStart == '\t'))//ok
        {
            pStart++;
            pEnd++;
        }

        if(*pEnd == '\0' || *pEnd == '\n')//exit when reading is not end but has not cmd
        {
            if(count == 0)
                return -1;
            break;
        }

        while(*pEnd != ' ' && *pEnd != '\0' && *pEnd != '\n')//plus pEnd
            pEnd++;

        if(count == 0)//reading command=paramaters[0],count=2
        {
            *command = pStart;
        parameters[0]=pStart;
            count += 2;
        }
        else if(count <= MAXARG)//reading parameters,parameter[1]=***,count=3,parameter[2]=***,count=4
        {
            parameters[count-1] = pStart;
            count++;
        }
        else
        {
            break;
        }

        if(*pEnd == '\0' || *pEnd == '\n')
        {
            *pEnd = '\0';
            isFinished = 1;
        }
        else
        {
            *pEnd = '\0';
            pEnd++;
            pStart = pEnd;
        }
    }
    parameters[count-1] = NULL;//parameter[3]=NULL,count=4
    return count;

}

//内部命令的解析执行
int builtin_cmd(char *command, char **parameters){
    pwd=getpwuid(getuid());//get recent uid
    if(strcmp(command,"exit")==0 || strcmp(command,"quit")==0)
        exit(0);
    else if(strcmp(command,"cd")==0)
    {
        char *cd_path = NULL;

        if(parameters[1] == NULL)//make "cd" as "cd .." 
        {
            parameters[1] = malloc(3 * sizeof(char));
            parameters[1][0]= '.';
            parameters[1][1]= '.';
            parameters[1][2]= '\0';
        }
        if(parameters[1][0] == '~')
        {
            cd_path = malloc(strlen(pwd->pw_dir)+strlen(parameters[1])); 
            if(cd_path == NULL)
            {
                printf("cd:malloc failed.\n");
            }
            strcpy(cd_path,pwd->pw_dir);
            strncpy(cd_path+strlen(pwd->pw_dir),parameters[1]+1,strlen(parameters[1]));
  
        }
        else
        {
            cd_path = malloc(strlen(parameters[1]+1));
            if(cd_path == NULL)
            {
                printf("cd:malloc failed.\n");
            }
            strcpy(cd_path,parameters[1]);
        }
        if(chdir(cd_path)!= 0)
            printf("-wshell: cd: %s:%s\n",cd_path,strerror(errno));
        free(cd_path);
    }
    else if(strcmp(command,"type")==0)
    {
    char *typeprompt;
        if((strcmp(parameters[1],"cd")==0) ||(strcmp(parameters[1],"exit")==0) || (strcmp(parameters[1],"type")==0))
        {
            typeprompt="shell内嵌";printf("%s 是 %s\n",parameters[1],typeprompt);
    }
    else if((strcmp(parameters[1],"if")==0) ||(strcmp(parameters[1],"else")==0) || (strcmp(parameters[1],"while")==0))
    {
           typeprompt="qjjshell关键字";printf("%s 是 %s\n",parameters[1],typeprompt);
    }
    else if(strcmp(parameters[1],"ls")==0)
    {
        typeprompt="别名";printf("%s 是 %s\n",parameters[1],typeprompt);
    }    
    else{
          return 1;
    }

    
    }
    return 0;
}


//进程信号处理
void sig_handler(int sig)//background process print child process pid when child process exited
{
    pid_t pid;
    int i;
    for(i=0;i<MAXPIDTABLE;i++)
        if(BPTable[i] != 0) //only handler the background processes
        {
            pid = waitpid(BPTable[i],NULL,WNOHANG);
            if(pid > 0)
            {
                printf("process %d exited.\n",pid);
                BPTable[i] = 0; //clear
            }
            else if(pid < 0)
            {
                if(errno != ECHILD)
                    perror("waitpid error");
            }
         }
    return;
}

//结构体的初始化
int parse_info_init(struct parse_info *info)
{
    info->flag = 0;
    info->in_file = NULL;
    info->out_file = NULL;
    info->command2 = NULL;
    info->parameters2 = NULL;
    return 0;
}

//命令的解析
int parsing(char **parameters,int ParaNum,struct parse_info *info)//"ls -l -a",3,struct,
{
    int i;
    parse_info_init(info);
    if(strcmp(parameters[ParaNum-1],"&") ==0)//judge wether backgroud process
    {
        info->flag |= BACKGROUND;
        parameters[ParaNum-1] = NULL;
        ParaNum--;
    }
    for(i=0;i<ParaNum;)
    {
        if(strcmp(parameters[i],"<<")==0 || strcmp(parameters[i],"<")==0)//input redirect,"cat < in.c"
        {
            info->flag |= IN_REDIRECT;
            info->in_file = parameters[i+1];//parameter[2]
            parameters[i] = NULL;//parameter[1]
            i+=2;//i=3
        }
        else if(strcmp(parameters[i],">")==0)//output redirect,"echo 'hello' > out.c"
        {
            info->flag |= OUT_REDIRECT;
            info->out_file = parameters[i+1];//parameter[3]
            parameters[i] = NULL;//parameter[2]
            i+=2;//i=4
        }
        else if(strcmp(parameters[i],">>")==0)
        {
            info->flag |= OUT_REDIRECT_APPEND;
            info->out_file = parameters[i+1];
            parameters[i] = NULL;
            i+=2;
        }
        else if(strcmp(parameters[i],"|")==0)
        {
            info->flag |= IS_PIPED;
            parameters[i] = NULL;
            info->command2 = parameters[i+1];
            info->parameters2= &parameters[i+1];
            break;
        }
        else
            i++;
    }
    return 1;
}

void main(){
    int status,i;
    pid_t pid;
    char *command = NULL;
    char **parameters;
    char prompt[max_prompt];
    int ParaNum;
    struct parse_info info;    
    pid_t ChdPid,ChdPid2;
    
    for(i=0;i<MAXPIDTABLE;i++)//进程组标志位的初始化
        BPTable[i] = 0;
    parameters = malloc(sizeof(char *)*(MAXARG+2));
    buffer = malloc(sizeof(char) * MAXLINE);
    if(parameters == NULL || buffer == NULL)//错误检测
    {
        printf("bashshell error:malloc failed.\n");
        return;
    }
    
    if(signal(SIGCHLD,sig_handler) == SIG_ERR)//进程结束或者意外停止的时候SIGCHLD会被发送给父进程 
        perror("signal() error");
    
    while(TRUE){    //一直运行
        int pipe_fd[2],in_fd,out_fd;
        display(prompt);//调用函数显示个性化提示性西
        ParaNum=readcmd(&command,parameters,prompt);//读取用户输入的参数,ParaNum=count,2个参数的时候,count=4
        if(-1 == ParaNum)
            continue;
        ParaNum--;//自减运算ParaNum=count=3
        parsing(parameters,ParaNum,&info);
       

         int resault;
     resault=builtin_cmd(command,parameters);
         if(strcmp(command,"type")==0 && resault)
        command="which";
    
    
         if(info.flag & IS_PIPED) //command2 不为空
        {                
            if(pipe(pipe_fd)<0)
            {
                printf("bashshell error:pipe failed.\n");
                exit(0);
            }
        }
        
          
        if((ChdPid=fork())==0){
            //child process     
           if(info.flag & IS_PIPED) //PIPED
            {                
                if(!(info.flag & OUT_REDIRECT) && !(info.flag & OUT_REDIRECT_APPEND)) // ONLY PIPED
               {
                    close(pipe_fd[0]);
                    close(fileno(stdout)); 
                    dup2(pipe_fd[1], fileno(stdout));
                    close(pipe_fd[1]);
                }
                else 
               {
                    close(pipe_fd[0]);
                    close(pipe_fd[1]);//send a EOF to command2
                    if(info.flag & OUT_REDIRECT) //OUT_REDIRECT and PIPED
                       out_fd = open(info.out_file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
                    else  //OUT_REDIRECT_APPEND and PIPED
                       out_fd = open(info.out_file, O_WRONLY|O_APPEND|O_TRUNC, 0666);
                    close(fileno(stdout)); 
                    dup2(out_fd, fileno(stdout));
                    close(out_fd);          
                }
            }
            else//NOT PIPED
            {
                if(info.flag & OUT_REDIRECT) // OUT_REDIRECT WITHOUT PIPE
               {
                    out_fd = open(info.out_file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
                    close(fileno(stdout)); 
                    dup2(out_fd, fileno(stdout));
                    close(out_fd);
                }
                if(info.flag & OUT_REDIRECT_APPEND) // OUT_REDIRECT_APPEND WITHOUT PIPE
               {
                    out_fd = open(info.out_file, O_WRONLY|O_CREAT|O_APPEND, 0666);
                    close(fileno(stdout)); 
                    dup2(out_fd, fileno(stdout));
                    close(out_fd);
                }
            }
            
            if(info.flag & IN_REDIRECT)//INREDIRECT
            {
                in_fd = open(info.in_file, O_CREAT |O_RDONLY, 0666);
                close(fileno(stdin)); 
                dup2(in_fd, fileno(stdin));
                close(in_fd); 
            }
            execvp(command,parameters);
        }
        else{
            //parent process
            if(info.flag & IS_PIPED)
            {
                if((ChdPid2=fork()) == 0) //command2
                {
            //children process
                    close(pipe_fd[1]);
                    close(fileno(stdin)); 
                    dup2(pipe_fd[0], fileno(stdin));
                    close(pipe_fd[0]); 
                    execvp(info.command2,info.parameters2);
                }
                else
                {
            //parent process
                    close(pipe_fd[0]);
                    close(pipe_fd[1]);
                    waitpid(ChdPid2,&status,0); //wait command2
                }
            }

            if(info.flag & BACKGROUND)//backgroud
            {
                printf("Child pid:%u\n",ChdPid);
                int i;
                for(i=0;i<MAXPIDTABLE;i++)
                    if(BPTable[i]==0)
                        BPTable[i] = ChdPid; //register a background process
                if(i==MAXPIDTABLE)
                    perror("Too much background processes\nThere will be zombine process");                    
            }
            else
            {          
                waitpid(ChdPid,&status,0);//wait command1
            } 
        }//end else

    }//end while
    free(parameters);
    free(buffer);
}
View Code

 

  • 运维脚本

文件备份相关的

rotate_log.sh [-nz] [-m|--mode copytruncate|move] [-s|--size maxsize] filename

 

#!/bin/bash

#全局变量,用来避免执行操作的时候覆盖已有的文件
i=1

#各执行函数
#—— 1—— 压缩参数-z
function execp_z(){
    gzip "$filepath"
}
#——2 ——询问是否备份参数-n
function execp_n(){
    echo "are you sure to backup""$filepath""?"
}
#——3 ——有大小限制的备份 -s(minfilesize)
function execp_s(){               
    real=`ls -l $filepath | awk '{ print $5 }'`
#start 将系统文件的大小和输入的阈值进行单位的统一,都统一为K
    max=$1
    max=${max/M/000}
    max=${max/G/000000}
    max=${max/K/}
    real=${real/K/}
#end 
#当系统文件的大小real大于输入的文件大小max的时候
    if [ "$max" -le "$real" ] ;then
    {
#文件的重名检查
    while [ -f "$filepath"".""$i" ] ;
     do  
         i=i+1;
     done;
#备份操作
     mv "$filepath" "$filepath"".""$i"  
    }    
    fi
}
#—— 4 ——分模式备份-mmove和-mcopytruncate
function execp_m(){
    if [ "$1" = 'move' ] ;then    
    {
    while [ -f "$filepath"".""$i" ] ;
    do 
        i=i+1;
    done;
    mv "$filepath" "$filepath"".""$i"
    }
    elif [ "$1" = 'copytruncate' ] ;then
    {
    while [ -f "$filepath"".""$i" ] ;
      do  
          i=$((i+1))
     done;
     cp "$filepath" "$filepath"".""$i"
     truncate --size 0  "$filepath"
    }    
    fi
}

#主解析函数,所有命令在这里解析
function execp(){
#num中存放从主函数传来的参数个数
    num=$#
#第一参数为n
    if [ "$1" = 'n' ] ;then
    {
#参数为-nz的情况
        if [ "$num" -eq 2 -a "$2"='z' ] ;then  
            execp_n
            execp_z
#参数为-n的情况
        elif [ "$num" -eq 1 ] ;then
            execp_n
        else 
            echo "$error"
        fi
    }
#第一个参数为z
    elif [ "$1" = 'z' ] ;then
    {
#参数为-zn的情况
        if [ "$num" -eq 2 -a "$2"='n' ] ;then
            execp_z
            execp_n
#参数为-z的情况
        elif [ "$num" -eq 1 ] ;then
            execp_z
        else
            echo "$error"
        fi
    }
#第一个参数为m
    elif [ "$1" = 'm' ] ;then
    {
#不带值的情况,默认为move模式
        if [ "$num" -eq 1 ] ;then
            execp_m 'move'
#带值的情况
        elif [ "$num" -eq 2 ] ;then
        {  
#符合值的取值 
            if [ "$2"='move' -o "$2"='copytruncate' ] ;then
                execp_m $2
            else 
                echo "$error"
            fi
        }
        else 
            echo "$error"
        fi
    }
##第一个参数为s
    elif [ "$1" = 's' ] ;then
    {
#带值的情况
        if [ "$num" -eq 2 ] ;then
            execp_s $2
        else
            echo "$error"
        fi
    }
    fi
}


#主函数 
#读取文件名
filename=${!#}
#读取当前路径 
pwd=$PWD
#拼接出文件绝对路径
filepath="$pwd"/"$filename"
#循环的分析logrotate.h后面的参数列表
for p in $@;
do
    if [ "$p" != "$filename" ] ;then
    {
#p中的字母数等于两个的情况,意味着为-n,-z,-m等可以不带值的参数
        if [ ${#p} -eq 2 ] ;then
        {   
#para中存放着参数的字母,例如m,n,z,s,等等
         para=${p:1:1}
#进入解析执行函数execp
         execp $para 
        }
#p中的字母数大于两个的情况,意味这为-s,-m等需要带值的参数,或者多个无值参数
        elif [ ${#p} -gt 2 ] ;then
        {
#para中存放参数的字母
        para=${p:1:1}
#mode中存放参数字母后面所带的值,例如-s500K,这里mode=500K
        mode=${p:2}
#进入解析执行函数
        execp $para $mode 
        }
        else 
            echo "error"
        fi
    }
    fi
done;
View Code