linux下新硬盘的自动检测及格式化--支持硬盘的热插拔处理

说明

可能存在bug,所以慎用!!! 且只在mbr分区格式下测试过。
parted.sh 可以用在系统起来的时候,比如rc.local脚本里面。

parted.c 需要parted.sh脚本配合使用,可以实现硬盘热插拔时的处
理,核心思想是linux下的文件系统变化通知机制。

parted 即parted.c的可执行文件。

欢迎大家一起讨论及指出其中的bug。

parted.sh的实现如下

    #!/bin/sh
    ##################rongp 2012-6-21###############

    PARTED=/sbin/parted
    MOUNTED_TOP_DIR=/disks/

    function mount_and_init {
        mkdir $2
        if mount -t ext4 $1 $2; then
            echo "$1 $2 ext4 defaults 0 0" >>/etc/fstab
            echo partition $1 mount to $2 is ready
        else
            echo mount
        fi
    }

    function remkpart {
        $PARTED -s $1 mklabel msdos #gpt
        $PARTED -s $1 mkpart primary ext4 $2 $3>/dev/null #maybe use -1 instead of $3
        mkfs.ext4 ${1}1 >/dev/null
        MOUNT_POINT=`fdisk -l $1 | grep "Disk identifier" | awk '{print $3}'`
        mount_and_init ${1}1 $MOUNTED_TOP_DIR/$MOUNT_POINT
    }

    function check_need_part {
        ret=`fdisk -l $1 2>/dev/null | grep "Disk identifier" | awk '{print $3}'`
        if [ "$ret" == "0x00000000" ]; then
            return 0
        else
            return 1
        fi
    }

    if [ "$1" == "" ]; then
        DISK=`find /dev/ -name sd[a-z]`
    else
        DISK="/dev/$1"
    fi

    [ -d "$MOUNTED_TOP_DIR" ] || mkdir $MOUNTED_TOP_DIR

    for tmpdisk in $DISK
    do
        check_need_part $tmpdisk
        if [ "$?" == "1" ]; then
            echo "$tmpdisk pass"
            continue;
        else
            echo "$tmpdisk need "
        fi

        echo "make a temp partion so parted can get disk size"
        $PARTED $tmpdisk mkpart primary 0 100 >/dev/null

        STARTSIZE=0
        #STOPSIZE='$PARTED $tmpdisk unit MB print | grep "Disk $tmpdisk" | cut -d: -f 2| cut -dM -f1` #maybe use -1  instead of STOPSIZE' #分区的结束位置
        STOPSIZE=$((`fdisk -s $tmpdisk`/1000)) #分区的结束位置,和上面一句同义
        remkpart $tmpdisk $STARTSIZE $STOPSIZE
    done

parted.c文件实现如下

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    #include <unistd.h>
    #include <sys/inotify.h>

    #define        BUF_SIZE    1024

    int main(void)
    {
        int    fd, wd;
        int    len = 0, pos = 0;
        char    buffer[BUF_SIZE];
        char    *path = "/dev/";
        char    buf[128];
        struct    inotify_event *event;
            
        fd = inotify_init();
        if (fd < 0) {
            perror("inotify_init");
            return -1;
        }
        
        wd = inotify_add_watch(fd, path, IN_CREATE | IN_DELETE/*IN_MOVED_TO*//*IN_ALL_EVENTS*/);
        if (wd < 0) {
            perror("inotify_add_watch");
            close(fd);
            return -1;
        }
        
        while(1) {
            memset(buf, 0, 128);
            len = read(fd, buffer, BUF_SIZE);

            while(len > 0) {
                event = (struct inotify_event *)(buffer+pos);
                if (event->wd != wd)
                    break;

                if (event->mask & IN_CREATE) {
                    if (!strncmp(event->name, "sd", strlen("sd"))
                     || !strncmp(event->name, "hd", strlen("hd"))) {
                        sprintf(buf, "sh parted.sh %s", event->name);
                        system(buf);
                    }
                }
                if (event->mask & IN_DELETE) {
                    if (!strncmp(event->name, "sd", strlen("sd"))
                     || !strncmp(event->name, "hd", strlen("hd"))) {
                        sprintf(buf, "fdisk -l /dev/%s 2>/dev/null | grep \"Disk identifier\" | awk '{print $3}'", "/sda");
                        char tmpbuf[128];
                        FILE *fp = popen(buf, "r");
                        fread(buf, 1, 1024, fp);
                        fclose(fp);
                        *strchr(buf, '\n') = 0;
                        sprintf(tmpbuf, "sed -i '/%s/d' /etc/fstab", buf);
                        system(tmpbuf);
                    }
                }

                len -= event->len+sizeof(struct inotify_event);
                pos += event->len+sizeof(struct inotify_event);
            }
            pos = 0;
        }
        close(fd);
        return 0;
    }

完!
2012年6月

posted @ 2017-10-14 10:16  rongpmcu  阅读(992)  评论(0编辑  收藏  举报