Shell 脚本欣赏区

以下代码是使用了script命令来捕获所有的击键操作,用于监视用户.
ps:学学严谨的作风.(korn与bash语法略有差别)
[code:1]
TS=$(date +%m%d%y%H%M%S)    #file time stamp
THISHOST=$(hostname|cut -f1-2 -d.)  #host name of this machine
LOGDIR=/usr/local/logs/script             #directory to hold the logs
LOGFILE=${THISHOST}.${LOGNAME}.$TS  #creates the name of the log file
touch $LOGDIR/$LOGFILE                       #creates the actual file

#set the command prompt
export PS1="[$LOGNAME:$THISHOST]@" '$PWD> '

############### run it here ######################

chown $LOGNAME ${LOGDIR}/${LOGFILE}  #let the user own the file during the script
chmod 600 ${LOGDIR}/${LOGFILE}     #change permission to RW for the ower

script ${LOGDIR}/${LOGFILE}      #start the script monitoring session

chown root ${LOGDIR}/${LOGFILE}   #change the ownership to root
chmod 400 ${LOGDIR}/${LOGFILE}   #set permission to read-only by root
[/code:1]
在CU看到的一段安全代码

[code:1]#! /bin/bash
# platinum, 2005.07.25
SCANNER=`grep "\`date \"+ %d %H:%M\" -d \"-1min\"\`" /var/log/secure|awk '/Failed/{print $(NF-3)}'|sort|uniq -c|awk '{print $1"="$2;}'`

for i in $SCANNER
do
       NUM=`echo $i|awk -F= '{print $1}'`
       IP=`echo $i|awk -F= '{print $2}'`
       echo $NUM
       echo $IP
       if [ $NUM -gt 5 ] && [ -z "`iptables -vnL INPUT|grep $IP`" ]
       then
               iptables -I INPUT -s $IP -m state --state NEW,RELATED,ESTABLISHED -j DROP
               echo "`date` $IP($NUM)" >> /var/log/scanner.log
       fi
done [/code:1]

放在cron中定时执行。
请问这些代码有什么用!!和怎么用?
我是新手!请大家多多指教!
记录登录终端与登录时间执行命令
[code:1]#!/bin/bash

logfilename=/var/log/typescript_`tty | awk -F/ '{print $(NF-1) $(NF)}'`.log
ls `echo $logfilename` >/dev/null 2>&1

if [ $? -ne 0 ];then
        touch `echo $logfilename`
fi

script -a `echo $logfilename`
[/code:1]
自己写的SHELL。
以此程序了解一些SHELL的运行机制。
像一般C一样编译运行就可以了。
[code:1]/*filename:mini.h*/
#define WHITESPACE    " ., &"
#define MAX_ARG_LEN        10
#define MAX_DIRS           20
#define MAX_PATH_LEN       100
#define STD_INPUT          0
#define STD_OUTPUT         1
#define MAX_ARGS           5
struct command_t {
int argc;
char *name;
char *argv[MAX_ARGS];
};[/code:1]

[code:1]/************************************************************
*MiniShell
*filename:mini.c
*it's a simple shell written by Manio(maniosterATgmail.com)
*Bugs:1.the commands must be seprated by only one whitespace
*and more and more bugs here...
*the part of pipe havn't be written.
*date,addr:08/16/2006 Yangshuo,China
************************************************************/
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include "mini.h"

//#define DEBUG 1

void printLineHead();
void parseCommand(char *,char **);
char *GetChkFullPath(char **,char **);

main(){
int i,j;/*for common use*/
int stat;/*used by wait()*/
int isInRedir,isOutRedir,isPipe;
int fid;/*for file opening*/
char orginalCmd[100];/*store the command user typed*/
char *dir[MAX_DIRS];

struct command_t command;
char *tempstr[7];

/*initial argv
   *maybe a error will be occured if argv is not be initialed
*/
for( i = 0 ; i < MAX_ARGS ; i++ )
    command.argv[i] = (char *)malloc(MAX_ARG_LEN);
   
      while( 1 ){
               printLineHead();
               gets(orginalCmd);  /* read user's input */
        #ifdef DEBUG
                      printf("::::after gets(orginalCmd):::: ");
                      printf("orginalCmd=%s ",orginalCmd);
                      printf(":::::::::::::::::::::::::::::: ");
        #endif
        /*if "exit" inputed,exit the shell*/
        if(strcmp(orginalCmd,"exit") == 0)
            break;
        /*devide command line to several parts*/
              parseCommand(orginalCmd,command.argv);
              /*get the amount of argv*/
              for(i = 0;command.argv[i] != NULL;i++);
              command.argc = i;
#ifdef DEBUG
              printf("command.argc=%d ",command.argc);
#endif
#ifdef DEBUG
    printf("::::parseCommand command.argv:::: ");
    printf("command.name = %s ",command.name);
    int commandi;
    for(commandi=0;command.argv[commandi]!=NULL;commandi++)
        printf("command.argv[%d]=%s ",commandi,command.argv[commandi]);
    printf("::::END command.argv:::: ");
#endif
   
            /*get the dirs from PATH;PATH is a enviroment var*/
#ifdef DEBUG
            printf("getDir start=========================== ");
#endif
            getDir(dir);
            
#ifdef DEBUG
    int diri=0;
    for(;dir[diri]!=NULL;diri++)
    {
        printf("in main dir[%d] is %s ",diri,dir[diri]);
    }
#endif
              /*get the name of command,this must get the full path of the file,but here is for debug*/
            command.name = GetChkFullPath(command.argv,dir);
#ifdef DEBUG
            printf("in main after GetChkFullPath command.name=%s ",command.name);
#endif
            if(command.name == NULL ){
                /*the command inputed is not valid or is empty*/
                continue;
                fprintf(stderr, "Command %s not found ", command.argv[0]);
            }
            /*scan  < > | ,isPipe isInRedir and isOutRedir store the position of "< > |" */
            isPipe = isInRedir = isOutRedir = 0;
            for( i= 0 ; command.argv[i] != NULL ; i++ )
            {
                if( strcmp( command.argv[i] , "<" ) == 0 ){
                    isInRedir = i;
                }
                if( strcmp( command.argv[i] , ">" ) == 0 ){
                    isOutRedir = i;
                }
                if( strcmp( command.argv[i] ,  "|" ) == 0 ){
                    isPipe = i;
                }
            }
#ifdef DEBUG
            printf("isin,inout,ispipe:%d%d%d ",isInRedir,isOutRedir,isPipe);
#endif
#ifdef DEBUG
            command.argv[3] = NULL;
            printf("show the argvs which is not set ");
            for(i = 0 ; i < MAX_ARGS ; i++)
                printf("argv[%d]=%s ",i,command.argv[i]);
#endif
                /*excute a commmand*/
        if(fork() == 0){
#ifdef DEBUG
            printf("::::::::::::::::In fork==0:::::::::::::::::: ");
#endif
            if(isInRedir){
                fid = open(command.argv[isInRedir + 1],O_RDONLY);
                close(STD_INPUT);//close standard input
                dup(fid);//redirect fid to standard input
                close(fid);
                command.argv[isInRedir] = NULL; /*ignore the word after isInRedir*/
#ifdef DEBUG
    printf("::::parseCommand command.argv:::: ");
    printf("command.name = %s ",command.name);
    for(commandi=0;command.argv[commandi]!=NULL;commandi++)
        printf("command.argv[%d]=%s ",commandi,command.argv[commandi]);
    printf("::::END command.argv:::: ");
#endif
            }
            if(isOutRedir){
                fid = open(command.argv[isOutRedir + 1],O_WRONLY|O_CREAT);
                close(STD_OUTPUT);
                dup(fid);
                close(fid);
                command.argv[isOutRedir] = NULL;
#ifdef DEBUG
    printf("::::parseCommand command.argv:::: ");
    printf("command.name = %s ",command.name);
    for(commandi=0;command.argv[commandi]!=NULL;commandi++)
        printf("command.argv[%d]=%s ",commandi,command.argv[commandi]);
    printf("::::END command.argv:::: ");
#endif
            }
            execv(command.name,command.argv);/*excute the command*/
#ifdef DEBUG
            printf("::::::::::::::::In fork==0 END:::::::::::::::::: ");
#endif
        }else{
#ifdef DEBUG
            printf("::::::::::::::::In fork!=0:::::::::::::::::: ");
#endif
            wait(&stat);/*wait for the end of child process*/
#ifdef DEBUG
            printf("::::::::child process done!::IN FORK!=0:END::::: ");
#endif
        }
//        loopcount = 0;
      }/*while*/
#ifdef DEBUG
      printf("Shell terminaled ");
#endif
}

void printLineHead()
{
printf(" MANIO's miniSHELL>");     
}
/**************************************************************
   parseCommand()
   *seprate cLine by WHITESPACE,put them to pchar[]
   *#define WHITESPACE    " ., &"
   *bugs:This code does not handle multiple WHITESPACE characters
***************************************************************
*/
void parseCommand(char *cLine, char *pchar[]) {
    int argc;
    char *tCLine;
    char **clPtr;
// Initialization
    tCLine = cLine;
    clPtr = &tCLine;
    argc = 0;
// This code does not handle multiple WHITESPACE characters
    while((pchar[argc++] = strsep(clPtr, WHITESPACE)) != NULL);

    pchar[argc--] = NULL;    // Null terminated list of strings
}


/****************************************************************
   *get the path in PATH seprated by ":"
*****************************************************************
*/
int  getDir(char *dir[])
{
    int i;
    char *s;
    char *oldpath;
    char *ppath;
    s=(char *)getenv("PATH");
#ifdef DEBUG
    printf("s is %s ",s);
    printf("s2=====%c ",s[2]);
#endif
    oldpath = (char *)malloc(strlen(s)+1);
    strcpy(oldpath,s);
#ifdef DEBUG
    printf("oldpath is %s ",oldpath);
#endif
    ppath = oldpath;
#ifdef DEBUG
    printf("ppath char  is %c ",*ppath);
#endif
   
    for(i=0;*ppath!='';ppath++)
    {
#ifdef DEBUG
    printf("in for ppath char  is %c ",*ppath);
#endif
        
        if(*ppath==':')
        {
            dir[i++] = oldpath;
            *ppath='';
            oldpath = ppath+1;   
        }
    }
    dir[i] = NULL;
#ifdef DEBUG
    int diri=0;
    for(;dir[diri]!=NULL;diri++)
    {
        printf("dir[%d] is %s ",diri,dir[diri]);
    }
#endif
    return 1;   
   
}

/****************************************************************
   *get and check the full path which the user inputed
    *dir :dirs in PATH
    *argv:argv in command_t
*****************************************************************
*/
char *GetChkFullPath(char **argv,char **dir)
{
#ifdef DEBUG
    printf(":::::::::::GetChkFullPath start ");
    printf("argv[0]=%s dir[0]=%s ",argv[0],dir[0]);
#endif
    char fullpath[MAX_PATH_LEN];
    char *result;
    int i;
   
    result = NULL;
    if( *argv[0] != '/' )
    {
        // *argv[0] != ''
#ifdef DEBUG
        printf("JUGE argv[0]!=/ ");
#endif
        for(i = 0;dir[i] != NULL ;i++)
        {
            strcpy(fullpath,dir[i]);
            strcat(fullpath,"/");
            strcat(fullpath,argv[0]);
#ifdef DEBUG
            printf("after strcat fullpath:%s ",fullpath);
#endif
            if(access(fullpath, X_OK | F_OK) != -1){
#ifdef DEBUG
                printf("FOUND %s in %s ",argv[0],dir[i]);
#endif
                result = (char *)malloc(strlen(fullpath)+1);
                strcpy(result,fullpath);
                break;
            }
        }        
    }else{
#ifdef DEBUG
    printf("JUGE argv[0]==/ ");
#endif
        if(access(argv[0], X_OK | F_OK) != -1){
#ifdef DEBUG
            printf("FOUND %s  ",argv[0]);
#endif
            result = (char *)malloc(strlen(argv[0])+1);
            strcpy(result , argv[0]);
        }
        
    }

    if(result == NULL ){
        printf("%s is not a command. ",argv[0]);
        return NULL;
    }else{
#ifdef DEBUG
        printf("GetChkFullPath end result == %s ",result);
#endif
        return result;
    }
}
[/code:1]
顶楼上的,虽然内容不是我一开始认为的shell脚本解释器,看了半天记住了一行:
execv(command.name,command.argv);/*excute the command*/
呵呵。

加入变量附值,表达式运算,条件语句,循环语句和函数及过程调用的功能吧。
可以参考《C语言大全》第四版第六部份。