Archive

Archive for June, 2009

Простой скрипт бэкапа типового веб-сервера

June 23rd, 2009

Скрипт может создавать локальный архив из указанных каталогов, с указанными исключениями; архив mysql-баз. Может закачивать их на указанный FTP-сервер. Автоматически удаляет старые архивные копии (два варианта правил). Есть поддержка полного и инкрементального бэкапов. Работает под FreeBSD и Linux. Есть шифрование архивов и отправка уведомления о результатах на электронную почту.
Текст всех файлов ниже. Возможно удобнее будет скачатьархив:
файл backup.sh

#!/bin/sh

# Kiloservers.com sample backup script
# Last changes from: 23-07-2009

# Global backup tasks
mysql="YES" # need backup mysql bases? YES || NO
filebackup="YES" # need perform backup local files? YES || NO
savelocalbackup="YES" # need save backup on local drive? YES || NO
uploadbackup="YES" # need upload backup to FTP server? YES || NO
encryptbackup="NO" # need encrypt backup? YES || NO. If "YES" setup "encryptkey".
emailresult="YES" # need send e-mail with the results of backup? YES || NO. If "YES" setup "emailforresult".

# Common parametrs
backuptype="full" # 'full' or 'incremental'-files changed after last full backup
scriptdir="/etc/backup-complect" # homedir of this script
backupdir="/home/backup" # where save local backup
incfile="incfile" # file/dirs include to backup. Change content of this file
exfile="exfile" # file/dirs exclude from backup. Change content of this file
minfreespace="5000" # Minimal free space on backup slice in MB to start backup
encryptkey="" # Secret key to encrypt backup. Min 10 symbols recommended. Make sure that this key is kept in a safe place!
gpgpath="/usr/local/bin/" # path to gpg program
ftppath="/usr/bin/" # path to ftp client program
emailforresult="" # e-mail for backup results
sendmailpath="/usr/sbin/" # path to sendmail program

# FTP settings
ftphost="" # backup host
ftpuser=""
ftppass=""

# SQL settings
sqluser="root"
sqlpass=""
sqlhost="localhost"
allbases="YES" # 'YES' or 'NO'. Backup all bases or only from 'backupsqlbases' parametr
backupsqlbases="mysql" # bases list separate by space
mysqlutilspath="/usr/local/bin/" # path to 'mysql' and 'mysqldump' folder. No need to change.
sqldef="--single-transaction --skip-add-locks --skip-disable-keys --force" # parametrs for mysqldump


#######################
##### just do it! #####
#######################

salt=`< /dev/urandom tr -dc A-Za-z0-9 | head -c8` # random string for more secure ftp uploads
freespace=`df -m $backupdir | grep dev | awk '{print $4}'` # current free space on backupdir slice
hostn=`hostname`
backupstartdate=`date "+%Y-%m-%d %H:%M %Z%n"`

# check to exist backupdir
if [ ! -d $backupdir ];  then
   echo "$backupdir backupdir is no exist! Backup canceled."
   exit
fi

# check to exist mysql/mysqldump program
if [ $mysql = YES ]; then
    if [ ! -f $mysqlutilspath"/mysql" ];  then
        mysqlutilspath="/usr/bin/"
        if [ ! -f $mysqlutilspath"/mysqldump" ];  then
            echo "mysqldump program is not exist on this path $mysqlutilspath ! Backup canceled."
            exit
        fi
    fi
fi

# check to email setup
if [ $emailresult = YES ]; then
    if [ $emailforresult = "" ]; then
        echo "You should setup emailforresult parametr. Backup canceled."
        exit
    fi

    if [ ! -f $sendmailpath"/sendmail" ];  then
        echo "You should setup sendmail before. Backup canceled."
        exit
    fi
fi

# check to exist ftp client program
if [ $uploadbackup = YES ]; then
    if [ ! -f $ftppath"/ftp" ];  then
        ftppath="/usr/local/bin/"
        if [ ! -f $ftppath"/ftp" ];  then
            echo "FTP client program is not exist on this path $ftppath ! Backup canceled."
            echo "To install ftp client on CentOS/RHEL:"
            echo "yum install ftp"
            exit
        fi
    fi

    # remove old ftp logs
    if [ -f $scriptdir"/ftpdump.txt" ];  then
        rm $scriptdir"/ftpdump.txt"
    fi
fi

# check to free space on backupdir
if [ $minfreespace -ge $freespace ]; then
    echo "Free space not enought! Backup canceled."
    exit
fi

# check gpg and secret key
gpgext=""
if [ $encryptbackup = YES ]; then
    if [ $encryptkey = "" ]; then
        echo "You must install the encryption key. Exit."
        exit
    fi

    if [ ! -f $gpgpath"/gpg" ];  then
        gpgpath="/usr/bin/"
        if [ ! -f $gpgpath"/gpg" ];  then
            echo "GnuPG v.1 is not found. You must setup path to GnuPG v.1 in gpgpath or setup GnuPG v.1."
            echo "To setup GnuPG v.1 on FreeBSD use:"
            echo "pkg_add -r gnupg1"
            echo "or"
            echo "cd /usr/ports/security/gnupg1 && make install"
            echo ""
            echo "To setup GnuPG v.1 on CentOS/RHEL use:"
            echo "yum install gnupg"
            echo ""
            echo "Backup canceled."
            exit
        fi
    fi
    gpgext=".gpg"
fi

# check OS
checkos=`uname -a | grep -c "FreeBSD"`

# if FreeBSD
if [ $checkos = "1" ]; then
    newerparam=" --newer-mtime-than "$scriptdir"/metka"
fi

# if Linux
if [ $checkos = "0" ]; then
    newerparam=" --newer "$scriptdir"/metka"
fi

if [ $backuptype = full ]; then
    newerparam=""
fi


incfile=$scriptdir"/"$incfile
exfile=$scriptdir"/"$exfile
curdate=`date "+%Y-%m-%d%n"`
curdatewithhours=`date "+%Y-%m-%d-%H%n"`

# get list of all mysql bases
if [ $mysql = YES ]; then
    echo "Get MySQL databases list"
    if [ $allbases = YES ]; then
        backupsqlbases=`echo "show databases"|$mysqlutilspath'mysql' --user=$sqluser --password=$sqlpass --host=$sqlhost|grep -v "^D"`
    fi
fi

# create remote current day folder
if [ $uploadbackup = YES ]; then
    echo "Create remote current day folder"
    ftp -i -n $ftphost 2>&1 1>>$scriptdir/ftpdump.txt <<END_SCRIPT
    quote USER $ftpuser
    quote PASS $ftppass
    mkdir /$curdate
    quit
END_SCRIPT
fi


if [ ! -d $backupdir"/"$curdate ];  then
    echo "Creating "$backupdir"/"$curdate
    mkdir $backupdir"/"$curdate
    chmod 777 $backupdir"/"$curdate
fi
cd $backupdir"/"$curdate

# create and upload mysql bases backup
if [ $mysql = YES ]; then
    echo "Begin export databases"
    for base in $backupsqlbases
        do
        $mysqlutilspath'mysqldump' $sqldef --user=$sqluser --password=$sqlpass --host=$sqlhost $base > $backupdir/$curdate/$base.sql
    done

    echo "Begin compress databases"
    nice -n 15 tar -cz -f $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz $backupdir/$curdate/*.sql
    rm $backupdir/$curdate/*.sql

    # get filesize
    if [ $checkos = "1" ]; then
        sqlbackupfilesize=`stat -f %z $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz`
        else
        sqlbackupfilesize=`stat -c %s $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz`
    fi

    if [ $encryptbackup = YES ]; then
        echo "Begin encrypt databases archive"

        echo "$encryptkey" | $gpgpath/gpg --no-tty --passphrase-fd 0 --cipher-algo AES256  -cq $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz
        rm $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz

        # get filesize for gpg files
        if [ $checkos = "1" ]; then
            sqlbackupfilesizegpg=`stat -f %z $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext`
            else
            sqlbackupfilesizegpg=`stat -c %s $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext`
        fi
    fi

    if [ $uploadbackup = YES ]; then
        echo "Begin upload databases archive"
        ftp -i -n $ftphost 2>&1 1>>$scriptdir/ftpdump.txt <<END_SCRIPT
        quote USER $ftpuser
        quote PASS $ftppass
        binary
        put $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext /$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext
        quit
END_SCRIPT
    fi

    if [ $savelocalbackup = NO ]; then
        echo "Remove local copy databases archive"
        rm $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz
        rm $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext
    fi
fi

# create and upload file backup
if [ $filebackup = YES ]; then
    echo "Begin compress files archive"

    nice -n 15 tar -cz $newerparam -f $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz -T $incfile -X $exfile

    # get filesize
    if [ $checkos = "1" ]; then
        filebackupfilesize=`stat -f %z $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz`
        else
        filebackupfilesize=`stat -c %s $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz`
    fi

    if [ $encryptbackup = YES ]; then
        echo "Begin encrypt files archive"

        echo "$encryptkey" | $gpgpath/gpg --no-tty --passphrase-fd 0 --cipher-algo AES256  -cq $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz
        rm $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz

        # get filesize for gpg files
        if [ $checkos = "1" ]; then
            filebackupfilesizegpg=`stat -f %z $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext`
            else
            filebackupfilesizegpg=`stat -c %s $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext`
        fi
    fi

    if [ $uploadbackup = YES ]; then
        echo "Begin upload files archive"
        ftp -i -n $ftphost 2>&1 1>>$scriptdir/ftpdump.txt <<END_SCRIPT
        quote USER $ftpuser
        quote PASS $ftppass
        binary
        put $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext /$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext
        quit
END_SCRIPT
    fi

    if [ $savelocalbackup = NO ]; then
        echo "Begin remove local copy files archive"
        rm $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz
        rm $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext
    fi
fi


# update special file for incremental backup
touch $scriptdir/metka

backupenddate=`date "+%Y-%m-%d %H:%M %Z%n"`

# send result e-mail
if [ -f $backupdir/report ];  then
    rm $backupdir/report
fi

if [ $emailresult = YES ]; then
    echo "Send a e-mail with the results"

    echo "Subject: $hostn `date "+%Y-%m-%d%n"` backup result" >> $backupdir/report

    echo "Backup started: $backupstartdate
Backup ended: $backupenddate" >> $backupdir/report

    echo "After backup free space on "$backupdir" - "`df -m $backupdir | grep dev | awk '{print $4}'`" MB" >> $backupdir/report

    if [ $filebackup = YES ]; then
        echo "Current file backup - "$filebackupfilesize" bytes - "$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz >> $backupdir/report

        if [ $encryptbackup = YES ]; then
            echo "Current encrypted file backup - "$filebackupfilesizegpg" bytes - "$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext >> $backupdir/report
        fi
    fi

    if [ $mysql = YES ]; then
        echo "Current mysql backup - "$sqlbackupfilesize" bytes - "$hostn-sql-backup-$curdatewithhours-$salt.tar.gz >> $backupdir/report

        if [ $encryptbackup = YES ]; then
            echo "Current encrypted mysql backup - "$sqlbackupfilesizegpg" bytes - "$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext >> $backupdir/report
        fi
    fi

    if [ $uploadbackup = YES ]; then
        echo "Error during ftp upload: " >> $backupdir/report
        cat $scriptdir"/ftpdump.txt" >> $backupdir/report
    fi

    echo "
Local backup folder statistics:" >> $backupdir/report
    if [ $checkos = "1" ]; then
        du -hc -d 1 $backupdir >> $backupdir/report
        else
        du -hc --max-depth=1 $backupdir >> $backupdir/report
    fi

    cat $backupdir/report | $sendmailpath"/sendmail" $emailforresult
    rm $backupdir/report
fi

echo "Backup complete"
exit

Файл exfile

/var/log/
/home/mysql
*.bz2
*.err
*.flv
*.log
*.zzz
*.rar
*.wmv
*.gz
*.bz2
*.avi
*.zip

Файл incfile

/etc
/usr/local/etc

файл install.txt

INSTALLATION:

1. Copy this folder to /etc/
2. Create "backupdir" folder
3. Edit "incfile" (dirs are included in the backup) and "exfile" (dirs deleted from the backup) files
4. If need - create SQL user for backup and set "mysql" to YES
5. If need - set "encryptbackup" to YES and set encryptkey. To decrypt use "gpg -o output_filename.tar.gz -d encrypted_filename.gpg"
6. Setup "emailforresult"
7. Configure spacer.sh to check the free space
8. Create cron task. For example, for full backup, at first day of month .. and check free space:
###################
5       7       1       *       *       root    /etc/backup-complect/spacer.sh 2> /dev/null
15       7       1       *       *       root    /etc/backup-complect/backup.sh 2> /dev/null
###################
9. Perform the test run:
cd /etc/backup-complect
./backup.sh


IMPORTANT!
Do not forget to do a test restore!

Файл spacer.sh

#!/bin/sh

# Kiloservers free space and count files checker.
# The script deletes old files from "backupdir" until not enough free space
# OR
# deletes old files from "backupdir" until number of files reaches the required
# Last changes from: 23-07-2009

# Settings
mode="space" # work mode: "space" or "count".
minfreespace="5000" # Minimal free space in MB. Actual for "space" mode
count="6" # how many files stored. Actual for "count" mode
backupdir="/home/backup" # directory to check

### Begin ###
echo "Mode $mode active"

# check OS
checkos=`uname -a | grep -c "FreeBSD"`

if [ $mode = "space" ]; then
    while [ `df -m $backupdir | grep dev | awk '{print $4}'` -lt $minfreespace ]
    do
        if [ $checkos = "1" ]; then
            filetodelete=`find $backupdir -type f -exec stat -f "%Sm %N" -t %Y%m%d%H%M%S {} \; | sort -n | head -1 | cut -d' ' -f2`
            else
            filetodelete=`find $backupdir -type f -exec stat -c "%Y %n" {} \; | sort -n | head -1 | cut -d' ' -f2`
        fi

        if [ -z $filetodelete ]; then
            echo "No files found. Exit"
            exit
            else
            rm $filetodelete
            echo "Deleted $filetodelete"
        fi
    done
fi

if [ $mode = "count" ]; then
    while [ `find $backupdir -type f | wc -l` -gt $count ]
    do
        if [ $checkos = "1" ]; then
            filetodelete=`find $backupdir -type f -exec stat -f "%Sm %N" -t %Y%m%d%H%M%S {} \; | sort -n | head -1 | cut -d' ' -f2`
            else
            filetodelete=`find $backupdir -type f -exec stat -c "%Y %n" {} \; | sort -n | head -1 | cut -d' ' -f2`
        fi

        if [ -z $filetodelete ]; then
            echo "No files found. Exit"
            exit
            else
            rm $filetodelete
            echo "Deleted $filetodelete"
        fi
    done
fi

echo "Check complete"

FreeBSD, linux, Uncategorized ,

Скрипт добавления зон для tinydns

June 16th, 2009

Для добавления одной зоны:

#!/bin/bash

DIR="/service/srvdns/root"
cd $DIR

if [ "x$1" = "x" ]; then
    echo "Usage: domain.com owner ip"
    exit
fi
if [ "x$2" = "x" ]; then
    echo "Usage: domain.com owner ip"
    exit
fi
if [ "x$3" = "x" ]; then
    echo "Usage: domain.com owner ip"
    exit
fi

domainexist=`cat $DIR/data | grep -c $1`
if [ $domainexist != "0" ]; then
    echo "$1 already exist. Exit."
    exit
fi

sed -e "s/domain.com/$1/g" "$DIR/domain.com" > "$DIR/tmpfile"
sed -e "s/owner/$2/g" "$DIR/tmpfile" > "$DIR/tmpfile2"
sed -e "s/serverip/$3/g" "$DIR/tmpfile2" >> "$DIR/data"

rm $DIR/tmpfile
rm $DIR/tmpfile2
make

Для добавления нескольких зон из файла-списка:

#!/bin/bash

DIR="/service/srvdns/root"
cd $DIR

if [ "x$1" = "x" ]; then
    echo "Usage: owner ip"
    exit
fi
if [ "x$2" = "x" ]; then
    echo "Usage: owner ip"
    exit
fi

cat $DIR/domainsfile | while read domain; do

    domainexist=`cat $DIR/data | grep -c $domain`
    if [ $domainexist != "0" ]; then
        echo "$domain already exist. Skipped."
        continue
    fi

    sed -e "s/domain.com/$domain/g" "$DIR/domain.com" > "$DIR/tmpfile"
    sed -e "s/owner/$1/g" "$DIR/tmpfile" > "$DIR/tmpfile2"
    sed -e "s/serverip/$2/g" "$DIR/tmpfile2" >> "$DIR/data"

    rm $DIR/tmpfile
    rm $DIR/tmpfile2
done
make

Где файл domain.com такой:

###########################
#owner: domain.com
.domain.com::ns1.domainserver.com.:2500
&domain.com::ns2.domainserver.com.:2500
@domain.com::mail.domain.com.:10:2500
+domain.com:serverip:2500
+*.domain.com:serverip:2500

dns ,

Добавление нового диска в Linux

June 10th, 2009

Проверяем, что диск виден в системе:

fdisk -l

Допустим, новый диск виден как /dev/sdb
Создаем раздел на нем:

fdisk /dev/sdb
n
p
2

Создаем фс:

mkfs.ext3 /dev/sdb1 -j

Создаем папку для монтирования, прописываем label новому диску, монтируем:

mkdir /mnt/newdisk
e2label /dev/sdb1 /mnt/newdisk
mount /dev/sdb1 /mnt/newdisk

Добавляем в fstab:

LABEL=/mnt/newdisk              /mnt/newdisk                    ext3    defaults        1 2

linux , ,

Автообновление базы GeoIP в CentOS

June 8th, 2009

Для базы по странам добавить в crontab:

cd /usr/share/GeoIP/ && wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz && gunzip -f GeoIP.dat.gz

Для базы по городам:

cd /usr/share/GeoIP/ && wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz && gunzip -f GeoLiteCity.dat && mv ./GeoLiteCity.dat ./GeoIPCity.dat

Uncategorized

Установка eAccelerator, ionCube, ZendOptimizer на CentOS

June 8th, 2009

Основной принцип этой связки – ZendOptimizer должен загружаться последним, а eAccelerator первым.
Т.е. после того как мы поставили Zend из бинарника, скачали и поставили ionCube, поставили eAccelerator:

yum --enablerepo=remi install php-eaccelerator.x86_64

Надо задизаблить строчку:

zend_extension="/usr/lib64/php/modules/eaccelerator.so"

в /etc/php.d/eaccelerator.ini

и сделать так:

[Zend]
Zend_extension="/usr/lib64/php/modules/eaccelerator.so"

zend_extension_manager.optimizer=/usr/local/Zend/lib/Optimizer-3.3.3
zend_extension_manager.optimizer_ts=/usr/local/Zend/lib/Optimizer_TS-3.3.3
zend_optimizer.version=3.3.3
zend_extension=/usr/local/Zend/lib/ZendExtensionManager.so
zend_extension_ts=/usr/local/Zend/lib/ZendExtensionManager_TS.so

php ,

Базовая установка LAMP в Debian

June 7th, 2009

Ставим апач:

apt-get install apache2 php5 libapache2-mod-php5 php5-curl

Конфиги в /etc/apache2/
Для добавления виртуалхоста создаем его конфиг (domain.com) в /etc/apache2/sites-available/ и:

a2ensite domain.com

Для выключения:

a2dissite domain.com

Для включения модулей апача:

a2enmod rewrite

Ставим мускул:

apt-get install mysql-server mysql-client php5-mysql

Конфиги в /etc/mysql/

Ставим nginx:

apt-get install nginx

linux , , , ,

Базовая настройка ipfilter

June 3rd, 2009

К пакету применяется последнее подходящее правило.
Параметры в rc.conf:

ipfilter_enable="YES"             # Запуск межсетевого экрана ipf
ipfilter_rules="/etc/ipf.rules"   # Загрузка файла с правилами
gateway_enable="YES"              # Включение шлюза для локальной сети
ipnat_enable="YES"                # Если надо задействовать nat
ipnat_rules="/etc/ipnat.rules"    # Определение файла правил для ipnat

Примеры правил в ipf.rules:

pass out quick on lo0 proto ip from any to any
pass in quick on lo0 proto ip from any to any
pass in quick on fxp1 proto tcp from any to 1.2.3.1/32 port = 80 flags S keep state
pass out log quick on fxp1 from 1.2.3.1/32 to any
pass in quick on fxp1 proto icmp from any to any icmp-type 0
pass in quick on fxp1 proto icmp from any to any icmp-type 11
block in log quick on fxp1 proto icmp from any to any
block return-icmp(port-unr) in log quick on tun0 proto udp from any to 20.20.20.0/24 port = 111

quick означает, что если анализируемый пакет подпадает под данное правило, то дальнейший просмотр правил прекращается.
keep state означает, что так же будут разрешены все пакеты, которые пойдут по этому же соединению в том числе в обратную сторону.

Примеры редиректов в ipnat.rules:

map tun0 192.168.1.0/24 -> 20.20.20.1/32
map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:30000

Запускаем:

/etc/rc.d/ipfilter start
/etc/rc.d/ipnat start

Команды:

ipf -Fa -f /etc/ipf.rules # сбросить все правила и загрузить новые из файла                              
ipfstat -in # вывод правил для входящего трафика
ipfstat -on # вывод правил для исходящего трафика
ipfstat -t # просмотр текущей статистики в виде TOP-а
ipnat -l # смотрим текущие редиректы для ipnat
/etc/rc.d/ipnat reload #для перезагрузки правил ната

FreeBSD , ,

Изменение media для сетевухи под linux

June 3rd, 2009

Меняем:

ethtool --change eth0 autoneg off speed 10 duplex full

Чтобы действовало после перезагрузки добавляем в файл /etc/sysconfig/network-scripts/ifcfg-eth0:

ETHTOOL_OPTS="autoneg off speed 10 duplex full"

linux ,