суббота, 27 июня 2009 г.

Какой дистрибутив установлен linux на компьютер

можно узнать с помощью утилиты lsb_release.
Пример использования

$ lsb_release -irc
Distributor ID: Ubuntu
Release: 9.04
Codename: jaunty
Если этой утилиты в исследуемой системе нет, то версию дистрибутивов, основанных на Debian/RedHat/Gentoo можно узнать так (спасибо Ярославу Шаповалу)
$ cat /etc/*release*
в дистрибутивах, основанных на Slackware
$ cat /etc/slackware-version
в SUSE
$ cat /etc/issue

суббота, 13 июня 2009 г.

Настройка DHCP клиента в Ubuntu

Дополнительная настройка DHCP-клиента может понадобится когда у вас есть локальный DNS-сервер или если DHCP-сервер провайдера работает с перебоями.

Пример файла конфигурации «/etc/dhcp3/dhclient.conf»

#
# dhcp3-client 3.1.1-5ubuntu8
#
# Сюда вписываем локальный адрес DNS-сервера
prepend domain-name-servers 127.0.0.1;

# Какие данные нужно затребовать с DHCP-сервера
request subnet-mask, broadcast-address, time-offset, routers,
# Комментируем, так как у нас локальный DNS-сервер
# domain-name, domain-name-servers, domain-search, host-name,
netbios-name-servers, netbios-scope, interface-mtu,
rfc3442-classless-static-routes, ntp-servers;

#
# dhclient будет использовать эти настройки, в то время,
# когда недоступен DHCP-сервер провайдера.
#
# Если не знаете что писать - загляните в файл
# /var/lib/dhcp3/dhclient.leases
#
lease {
interface "eth1";
fixed-address 72.xxx.xxx.xxx;
option subnet-mask 255.255.xxx.xxx;
option time-offset 32400;
# Если прописать адреса роутеров, dhclient проверит наличие
# первого роутера. В случае, если роутер не ответил
# на пинг, этот блок (lease) отбрасывается.
option routers 72.xxx.xxx.1;
option dhcp-lease-time 1800;
option dhcp-message-type 5;
option domain-name-servers 127.0.0.1;
option dhcp-server-identifier 72.xxx.xxx.xxx;
# По документации следующие строки должны быть
# в обязательном порядке. Время желательно
# выставить как можно большее, чтобы не стало
# просроченным.
renew 2 2037/01/12 00:00:00;
rebind 2 2037/01/12 00:00:00;
expire 2 2037/01/12 00:00:00;
}
Более подробно о других настройках можно прочитать в «man dhclient.conf»

понедельник, 8 июня 2009 г.

Работа Ubuntu Linux без носителя

Нужно было добиться загрузки Ubuntu в оперативную память компьютера и дальнейшей работы без носителя, с которого он был загружен. Решение получилось достаточно простым.
Вкратце идея такая: initrd.img изменяется так, чтобы, после загрузки и старта ядра, с носителя в память копировался файл со сжатым образом файловой системы корневого раздела (SquashFS). Далее поверх корневого раздела монтируется aufs-tmpfs и стартует Ubuntu.

Ниже будет описание как создать загрузочный iso-образ и бутовую USB-флешку.

  1. Создаем директории
    $ mkdir -p ~/ubuntu-ram/{etc,tmp,image,scripts}

  2. Устанавливаем необходимые пакеты
    $ sudo aptitude install lilo mtools genisoimage debootstrap syslinux squashfs-tools

  3. Копируем настройки initramfs
    Конфиги initramfs для iso-образа
    $ cp -a /etc/initramfs-tools ~/ubuntu-ram/etc/iso
    Конфиги initramfs для iso-образа
    $ cp -a /etc/initramfs-tools ~/ubuntu-ram/etc/usb

  4. Настраиваем окружение загружаемой системы
    $ export IMGROOT=~/ubuntu-ram/image
    $ sudo -E -s
    # debootstrap jaunty $IMGROOT http://mirror.ubuntu.optilink.ru/ubuntu/
    # echo "aufs / aufs rw 0 0" > $IMGROOT/etc/fstab
    # cp /etc/apt/sources.list $IMGROOT/etc/apt/
    # cp /etc/resolv.conf $IMGROOT/etc/
    # cat <<EOF > $IMGROOT/etc/hosts
    127.0.0.1 localhost.localdomain localhost
    127.0.1.1 hostname.domain hostname
    EOF

    # cat <<EOF > $IMGROOT/etc/network/interfaces
    auto lo
    iface lo loopback
    EOF

    # echo "hostname.domain" > $IMGROOT/etc/hostname
    # mount -t proc none $IMGROOT/proc
    # mount -o bind /dev $IMGROOT/dev
    # mount -t devpts none $IMGROOT/dev/pts
    # mount -t sysfs none $IMGROOT/sys
    Входим в изолированное окружение
    # chroot $IMGROOT bash
    Создаем аккаунт администратора и русскую локаль. Также разрешаем группе adm использование команды sudo
    # adduser --gecos 'System Administrator' demiurg
    # usermod -a -G adm demiurg
    # echo "@adm ALL=NOPASSWD: ALL" >> $IMGROOT/etc/sudoers
    # locale-gen ru_RU.UTF-8
    Устанавливаем ядро и требуемые утилиты
    # aptitude update
    # aptitude install linux-image-server grub aufs-tools squashfs-tools
    Настраиваем часовой пояс и консоль
    # dpkg-reconfigure tzdata
    # dpkg-reconfigure console-setup
    Далее система настраивается под себя (ставим дополнительные программы, правим конфиги под себя).

    Выходим из изолированного окружения
    # aptitude clean
    # exit
    Отмонтируем файловые системы
    # umount $IMGROOT/proc
    # umount $IMGROOT/dev/pts
    # umount $IMGROOT/dev
    # umount $IMGROOT/sys
    Выходим из режима суперпользователя
    # exit
    $

  5. Переходим к настройке конфигов initramfs для iso-образа
    Создаём так называемый хук (hook) - скрипт, вызываемый утилитой initramfs
    $ cat <<EOF > $IMGROOT/../etc/iso/hooks/load_modules
    #!/bin/sh
    set -e

    PREREQ=""

    prereqs () {
    echo "$PREREQ"
    }

    case $1 in
    prereqs)
    prereqs
    exit 0
    ;;
    esac

    . /usr/share/initramfs-tools/hook-functions

    force_load squashfs
    force_load isofs
    force_load aufs

    exit 0
    EOF
    $ chmod +x $IMGROOT/../etc/iso/hooks/load_modules
    Создаем скрипты, выполняющиеся во время загрузки initrd
    Скрипт, закидывающий образ системы в память
    $ cat <<EOF > $IMGROOT/../etc/iso/scripts/init-premount/udev_into_ram
    #!/bin/sh

    PREREQ=""

    prereqs () {
    echo "$PREREQ"
    }

    case $1 in
    prereqs)
    prereqs
    exit 0
    ;;
    esac

    mknod /dev/loop0 b 7 0
    mkdir /disk

    WAIT_COUNT=15
    while [ ! -e /dev/scd0 ] && [ "$WAIT_COUNT" -gt 0 ]
    do
    tmp=$((WAIT_COUNT-=1))
    sleep 1
    done

    echo -n "Please wait... "
    mount -t iso9660 -o ro /dev/scd0 /disk
    cp /disk/root.sqfs /
    echo "done"
    umount /disk && rm -Rf /disk
    EOF
    $ chmod +x $IMGROOT/../etc/iso/scripts/init-premount/udev_into_ram
    Скрипт, монтирующий файловую систему aufs
    $ cat <<EOF > $IMGROOT/../etc/iso/scripts/init-bottom/aufs_root
    #!/bin/sh
    #
    # https://help.ubuntu.com/community/aufsRootFileSystemOnUsbFlash
    #
    # Copyright 2008 Nicholas A. Schembri State College PA USA
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program. If not, see
    # <http://www.gnu.org/licenses/>.

    # Thank you Voyage Linux for the idea, http://voyage.hk/ Great job on release 0.5
    #
    # Tested with 8.04.1
    #
    #
    # ****************************************************************************************
    #
    # Change log
    #
    # 2008.08.01 Added debugging comments in "drop to a shell" section. grub option aufs=tmpfs-debug will stop the init script.
    # reviewed *********** fix fstab on tmpfs ******************
    # rootaufs failed when system was booted with /dev/xxx and fstab had uuid= info.
    # BlaYO pointed out the best and simplest solution was to use grep -v. Grep replaces a sed one liner.
    # Add the comment block to fstab
    #
    #
    #

    case $1 in
    prereqs)
    exit 0
    ;;
    esac

    export aufs

    for x in $(cat /proc/cmdline); do
    case $x in
    root=*)
    ROOTNAME=${x#root=}
    ;;
    aufs=*)
    aufs=${x#aufs=}
    case $aufs in
    tmpfs-debug)
    aufs=tmpfs
    aufsdebug=1
    ;;
    esac
    ;;
    esac
    done

    if [ "$aufs" != "tmpfs" ]; then
    #not set in boot loader
    #I'm not loved. good bye
    exit 0
    fi

    # This is a simple overview of the steps needed to use aufs on the root file system and see the /rw and /ro branches.
    # initramfs init-botton script
    # move the root file system to aufs/unionfs readonly /ro
    # root is mounted on ${rootmnt}
    # create tmpfs on /rw
    # create a aufs using /ro and /rw
    # put some files on the tmpfs to fix mtab and fstab
    # move aufs to rootmnt to finish the init process.
    # No changes to the root file system are made by this script.
    #
    # Why!
    # This will allow you to use a usb flash drive and control what is written to the drive.
    # no need to rebuild the squashfs file just to add a program.
    # boot to single user mode. The system works the way you expect. boot aufs=tmpfs and no changes are written to the flash.
    # run ubuntu on an eeePC .

    # Install
    # Install ubuntu 8.04 Hardy. Hardy has aufs installed by default
    # apt-get update
    # apt-get dist-upgrade
    # apt-get install aufs-tools
    # echo aufs >> /etc/initramfs-tools/modules
    # put this file in /etc/initramfs-tools/scripts/init-bottom/rootaufs
    # chmod 0755 rootaufs
    # # clean up menu.lst
    # update-grub
    # update-initramfs -u
    # vi /boot/grub/menu.lst
    # add aufs=tmpfs to the default entry.
    # do not add this line to single user mode.
    # boot to single user mode in order to install software.
    # note: if your home account is on the root file system, your files are in ram and not saved.
    #


    echo
    echo " root-aufs: Setting up aufs on ${rootmnt} as root file system "
    echo

    modprobe -q --use-blacklist aufs
    if [ $? -ne 0 ]; then
    echo root-aufs error: Failed to load aufs.ko
    exit 0
    fi

    #make the mount points on the init root file system
    mkdir /aufs
    mkdir /rw
    mkdir /ro

    # mount the temp file system and move real root out of the way
    mount -t tmpfs aufs-tmpfs /rw
    mount --move ${rootmnt} /ro
    if [ $? -ne 0 ]; then
    echo root-aufs error: ${rootmnt} failed to move to /ro
    exit 0
    fi


    mount -t aufs -o dirs=/rw:/ro=ro aufs /aufs
    if [ $? -ne 0 ]; then
    echo root-aufs error: Failed to mount /aufs files system
    exit 0
    fi


    #test for mount points on aufs file system
    [ -d /aufs/ro ] || mkdir /aufs/ro
    [ -d /aufs/rw ] || mkdir /aufs/rw

    # the real root file system is hidden on /ro of the init file system. move it to /ro
    mount --move /ro /aufs/ro
    if [ $? -ne 0 ]; then
    echo root-aufs error: Failed to move /ro /aufs/ro
    exit 0
    fi

    # tmpfs file system is hidden on /rw
    mount --move /rw /aufs/rw
    if [ $? -ne 0 ]; then
    echo root-aufs error: Failed to move /rw /aufs/rw
    exit 0
    fi



    #*********** fix fstab on tmpfs ******************
    # test for /dev/sdx
    # this is not on the real file system. This is created on the tmpfs each time the system boots.
    # The init process will try to mount the root filesystem listed in fstab. / and swap must be removed.
    # the root file system must be mounted on /ro not on /

    if [ "$aufsdebug" -eq 1 ]; then
    echo " root-aufs debug: Remove the root file system and swap from fstab "
    echo
    echo
    echo " ROOTNAME $ROOTNAME "
    echo " resume $resume "
    echo
    echo ' BlaYO pointed out that grep can be used to quickly remove '
    echo ' the root file system from fstab. '
    echo
    echo ' Thank you BlaYO for the debug info.'
    echo

    fi
    # old code
    # I'm sure that sed can do this in one step but I want to correct on the rootname not matching the root in fstab.
    #cat /aufs/ro/etc/fstab|sed -e s/$ROOTNAME/\#$ROOTNAME/ -e s/$resume/\#$resume/ >/aufs/etc/fstab

    #Add the comment block to fstab
    cat <<EOF >/aufs/etc/fstab
    #
    # RootAufs has mounted the root file system in ram
    #
    # This fstab is in ram and the real fstab can be found /ro/etc/fstab
    # the root file system ' / ' has been removed.
    # All Swap files have been removed.
    #

    EOF

    #remove root and swap from fstab
    cat /aufs/ro/etc/fstab|grep -v ' / ' | grep -v swap >>/aufs/etc/fstab
    if [ $? -ne 0 ]; then
    echo root-aufs error: Failed to create /aufs/etc/fstab
    #exit 0
    fi




    # add the read only file system to fstab
    #ROOTTYPE=$(/lib/udev/vol_id -t ${ROOT})
    ROOTTYPE=$(cat /proc/mounts|grep ${ROOT}|cut -d' ' -f3)
    ROOTOPTIONS=$(cat /proc/mounts|grep ${ROOT}|cut -d' ' -f4)
    echo /dev/loop0 /ro squashfs ro,relatime 0 0 >>/aufs/etc/fstab

    # S22mount on debian systems is not mounting /ro correctly after boot
    # add to rc.local to correct what you see from df
    #replace last case of exit with #exit
    cat /aufs/ro/etc/rc.local|sed 's/\(.*\)exit/\1\#exit/' >/aufs/etc/rc.local
    echo mount -f /ro >>/aufs/etc/rc.local

    # add back the root file system. mtab seems to be created by one of the init proceses.
    echo "echo aufs / aufs rw,xino=/rw/.aufs.xino,br:/rw=rw:/ro=ro 0 0 >>/etc/mtab" >>/aufs/etc/rc.local
    echo "echo aufs-tmpfs /rw tmpfs rw 0 0 >>/etc/mtab" >>/aufs/etc/rc.local
    echo exit 0 >>/aufs/etc/rc.local


    #build remountrw
    echo \#!/bin/sh >/aufs/bin/remountrw
    echo mount -o remount,rw ${ROOT} >>/aufs/bin/remountrw
    chmod 0700 /aufs/bin/remountrw

    #build remountro
    echo \#!/bin/sh >/aufs/bin/remountro
    echo mount -o remount,ro ${ROOT} >>/aufs/bin/remountro
    chmod 0700 /aufs/bin/remountro

    # This should drop to a shell. (rewrite)
    if [ "$aufsdebug" -eq 1 ]; then
    echo
    echo " root-aufs debug: mount --move /aufs ${rootmnt} "
    echo
    echo ' root-aufs debug: init will stop here. '
    echo
    exit 0
    fi

    mount --move /aufs ${rootmnt}

    exit 0
    EOF
    $ chmod +x $IMGROOT/../etc/iso/scripts/init-bottom/aufs_root
    На этом настройка initramfs заканчивается.

  6. Создаём скрипт, создающий iso-образ и сохраняем его в файле «~/ubuntu-ram/scripts/make-iso.sh»
    #!/bin/sh
    WORKDIR=/path/to/ubuntu-ram
    SQUASHFS_ROOT=$WORKDIR/image/
    ISO_ROOT=$WORKDIR/tmp/

    rm -Rf $ISO_ROOT/*

    # Получаем версию ядра в окружении
    version=$(basename $(readlink $SQUASHFS_ROOT/initrd.img))
    version=${version#initrd.img-}

    mount -o bind $WORKDIR/etc/iso $SQUASHFS_ROOT/etc/initramfs-tools
    chroot $SQUASHFS_ROOT mkinitramfs -v -o /boot/initrd.img-$version $version
    umount $SQUASHFS_ROOT/etc/initramfs-tools

    mkdir $ISO_ROOT/isolinux
    cp $SQUASHFS_ROOT/boot/initrd.img-$version $ISO_ROOT/isolinux/initrd.gz
    cp $SQUASHFS_ROOT/boot/vmlinuz-$version $ISO_ROOT/isolinux/vmlinuz
    cp /usr/lib/syslinux/isolinux.bin $ISO_ROOT/isolinux/
    cat <<EOF > $ISO_ROOT/isolinux/isolinux.cfg
    DEFAULT server
    TIMEOUT 1
    LABEL server
    menu label ^Server
    kernel vmlinuz
    append initrd=initrd.gz root=/root.sqfs loop=/dev/loop0 rootfstype=squashfs aufs=tmpfs ro
    EOF

    #
    mksquashfs $SQUASHFS_ROOT $ISO_ROOT/root.sqfs \
    -e $SQUASHFS_ROOT/boot/* \
    $SQUASHFS_ROOT/initrd.img \
    $SQUASHFS_ROOT/vmlinuz

    # Создаём ISO
    mkisofs -o $WORKDIR/image.iso -r \
    -V "MYUSBSERVER" -v -no-emul-boot \
    -boot-load-size 4 -boot-info-table \
    -b isolinux/isolinux.bin \
    -c isolinux/isolinux.boot $ISO_ROOT
    Делаем его исполняемым
    $ chmod +x ~/ubuntu-ram/scripts/make-iso.sh
    После выполнения скрипта в директории «~/ubuntu-ram» будет создан требуемый iso-образ.

  7. Создание загрузочной USB флешки.
    Создаём хук
    $ cat <<EOF > ~/ubuntu-ram/etc/usb/hooks/load_modules
    #!/bin/sh
    set -e

    PREREQ=""

    prereqs () {
    echo "$PREREQ"
    }

    case $1 in
    prereqs)
    prereqs
    exit 0
    ;;
    esac

    . /usr/share/initramfs-tools/hook-functions

    force_load usb_storage
    force_load squashfs
    force_load vfat
    force_load aufs

    exit 0
    EOF
    $ chmod +x ~/ubuntu-ram/etc/usb/hooks/load_modules
    Копируем скрипт «etc/iso/scripts/init-bottom/aufs_root» в «etc/usb/scripts/init-bottom/aufs_root».
    Пишем скрипт, загружающий систему из USB-флешки в оперативную память
    $ cat <<EOF > ~/ubuntu-ram/etc/usb/scripts/init-premount/udev_into_ram
    #!/bin/sh

    PREREQ=""

    prereqs () {
    echo "$PREREQ"
    }

    case $1 in
    prereqs)
    prereqs
    exit 0
    ;;
    esac

    mknod /dev/loop0 b 7 0
    mkdir /disk

    WAIT_COUNT=15
    while [ ! -e /dev/disk/by-label/MYUSBSERVER ] && [ "$WAIT_COUNT" -gt 0 ]
    do
    tmp=$((WAIT_COUNT-=1))
    sleep 1
    done

    echo -n "Please wait... "
    mount -t vfat -o ro /dev/disk/by-label/MYUSBSERVER /disk
    cp /disk/root.sqfs /
    echo "done"
    umount /disk && rm -Rf /disk
    EOF
    $ chmod +x $IMGROOT/../etc/usb/scripts/init-premount/udev_into_ram
    Ниже приведён скрипт создающий бутовую USB-флешку. Скрипт сохраняется в файл «~/ubuntu-ram/scripts/make-usb.sh»
    #!/bin/sh

    WORKDIR=/path/to/ubuntu-ram
    SQUASHFS_ROOT=$WORKDIR/image/
    ISO_ROOT=$WORKDIR/tmp/

    rm -Rf $ISO_ROOT/*

    # Получаем версию ядра в окружении
    version=$(basename $(readlink $SQUASHFS_ROOT/initrd.img))
    version=${version#initrd.img-}

    mount -o bind $WORKDIR/etc/usb $SQUASHFS_ROOT/etc/initramfs-tools
    chroot $SQUASHFS_ROOT mkinitramfs -v -o /boot/initrd.img-$version $version
    umount $SQUASHFS_ROOT/etc/initramfs-tools

    mkdir $ISO_ROOT/isolinux
    cp $SQUASHFS_ROOT/boot/initrd.img-$version $ISO_ROOT/initrd.gz
    cp $SQUASHFS_ROOT/boot/vmlinuz-$version $ISO_ROOT/vmlinuz
    cat <<EOF > $ISO_ROOT/syslinux.cfg
    DEFAULT server
    TIMEOUT 1
    LABEL server
    menu label ^Server
    kernel vmlinuz
    append initrd=initrd.gz root=/root.sqfs loop=/dev/loop0 rootfstype=squashfs aufs=tmpfs ro
    EOF

    #
    mksquashfs $SQUASHFS_ROOT $ISO_ROOT/root.sqfs \
    -e $SQUASHFS_ROOT/boot/* \
    $SQUASHFS_ROOT/initrd.img \
    $SQUASHFS_ROOT/vmlinuz

    echo "Please insert USB flash drive and press Enter"
    read
    # /dev/sdX - Ваша USB-флешка
    lilo -M /dev/sdX
    lilo -A /dev/sdX 1
    mkfs.vfat /dev/sdX1
    syslinux -f /dev/sdX1
    mlabel -i /dev/sdX1 ::MYUSBSERVER
    mount -t vfat /dev/sdX1 /mnt
    cp -a $ISO_ROOT/* /mnt
    umount /mnt
    exit 0
    Делаем скрипт исполняемым
    $ chmod +x ~/ubuntu-ram/scripts/make-usb.sh