Добрый день, читатели!
Наверняка каждый разработчик, рано или поздно, сталкивается с проблемой тестового окружения. Не очень удобно держать ПК включенным 24х7, да еще и заваливать его софтом для экспериментов под завязку. С другой стороны найти
Disclaimer: пост публикуется по просьбе icepro, поэтому не спешите менять карму мне, а лучше помогите хорошему человеку с инвайтом. Вы не найдете тут откровений или неожиданных решений, но проходя подобный путь сможете найти все необходимое в одном месте.
Заранее предупрежу: статья первая, сильно не бейте.
А теперь к деталям. Заранее прошу бородатых админов и всех компетентных в данной теме людей, не хвататься за сердце, фукать и спешить ставить минусы, ведь я только учусь и администрированием плотно не занимался. Зато надеюсь начинающим смогу сократить путь в Linux на пару шагов и пройти быстрое знакомство действительно быстро :)
Краткое содержание
Начинка
Итак, идея есть, начнем воплощать. Самым главным критерием для меня при выборе железа были — цена, низкое энергопотребление и отсутствие шума (иначе был риск что жена отправит мою песочницу на балкон, да еще может и со мной вместе:) ). Все это указывало на то, что целевым будет формфактор — MiniITX.
Побродив по интернет магазинам я нашел вот такую материнскую плату: Intel BOXD2500HN.
Базируется она на процессоре Intel Atom D2500 (1.86 ГГц). Для меня этой мощности было предостаточно. Потребляет энергии — 10 Ватт. Цена — около $70. Охлаждение пассивное — шума нету. Так же дома валялась SO-DIMM память на 2 ГБ и полутерабайтный винт.
Теперь о корпусе. Опять таки хотелось меньше шума, и поэтому выбор пал на корпус со внешним БП — DELUX E-2012 Black Mini-ITX
Итого единственный кулер — 40 мм, размещенный над жестким диском (ну было штатное место, вот и решил укомплектовать полностью).
OS
Выбор операционки был не долгим. Ранее приходилось работать с Ubuntu, поэтому выбор пал на ее фундамент — Debian. На момент написания статьи последней версией (которую я и установил) была 7.0 — Wheezy. Скачать ее можно на оффсайте, там она представлена в нескольких вариациях в зависимости от графической оболочки. Голую консоль я ставить не решился, и поэтому среди представленных вариантов выбрал самую легковесную — LXDE.
Сразу оговорюсь — Debian поразила меня богатством софтового репозитория. В нем можно найти все что угодно. Для того что бы поискать по имени интересующую программу воспользуемся командой:
sudo apt-cache search <название программы, или его часть>
для установки выполняем
sudo apt-get install <название программы>
Далее по тексту я буду упоминать об установке софта, но вы уже будете знать как это делать.
Ставить Debian не сложно. Скачиваем образ и делаем загрузочную USB флешку (сделать ее поможет LinuxLive USB Creator). Далее загружаемся с нее и включаем графический установщик (так будет проще). В основном установка похожа на установку windows: жмем Далее, Далее, Далее. Но некоторые моменты все же есть:
— на шаге выбора разметки выбираем отдельные разделы
— после того как мастер авторазбивки диска покажет вам предполагаемую структуру — не соглашайтесь, увеличьте RootFS (она же "/") хотя бы до пары гигабайт (у меня сейчас 512 Мб и за разделом приходится очень пристально следить)
— выбор программного обеспечения оставляем как есть (галки на «Окружение рабочего стола» и «Стандартная система», остальное поставим позже)
Если все же нужна пошаговая помощь при установке то рекомендую на просторах интернета найти маунал «Web-сервер на Debian GNU_Linux для начинающих».
Далее было произведено несколько мелких твиков системы:
-
sudo
Для того что бы иметь возможность вашему пользователю исполнять команды от имени суперпользователя, его нужно добавить в sudoer list. Детали настройки можно найти в документе который я уже упоминал выше, в разделе «1.2.1 Базовая настройка sudo»
-
Удаленный доступ
Дабы иметь возможность удаленного доступа, я сейчас говорю не про ssh, а как раз рабочий стол, был установлен VNC сервер — x11vnc.
Настройка довольно легкая, сначала генерируем авторизационный файл:x11vnc -storepasswd <pass> <file>
а потом добавим VNC сервер в автозагрузку (/etc/xdg/lxsession/LXDE/autostart)
@/usr/bin/x11vnc -dontdisconnect -display :0 -notruecolor -noxfixes -shared -forever -rfbport 5900 -bg -o /var/log/x11vnc.log -rfbauth /home/ice/.vnc/passwd
-
Autologin
Материнская плата умеет восстанавливать свое состояние после того как электричество было прервано и возобновлено. Но если к серверу не подключен монитор и не видно состояния системы, то после перебоев в электросети графическая среда так и будет висеть на странице Login после перезагрузки. Для того что бы устранить это неудобство добавим возможность автовхода для нашего пользователя, для этого в файл /etc/lightdm/lightdm.conf добавим строки:
autologin-user=ice autologin-user-timeout=0
-
Hardware монитор
Следить за оборудованием поможет
lshw lshw-gtk
Для мониторинга температуры я доставил lm-sensors и hddtemp.
Командаsensors
показывает информацию о МП с доступных датчиков.
Перед использованием утилиты нужно что бы она обнаружила все датчики, для этого требуется запустить:
/usr/sbin/sensors-detect
А команда
hddtemp /dev/sda
подсказывает до какой температуры нагрелся жесткий диск.
Первое время у меня была мания проверять температуру и другие датчики, поэтому я написал кратенький скрипт для сбора и логирования данных:
#!/bin/bash echo '################## TIME ##################' date echo '################# UP TIME ################' uptime echo '################# MB TEMP ################' sensors echo '################ HDD TEMP ################' sudo hddtemp /dev/sda echo echo
Теперь создадим расписание запуска скрипта, но предварительно выдадим ему права на выполнение:
visudo ice ALL=NOPASSWD: /home/ice/scripts/monitoring/temp.sh
а теперь Cron:
sudo crontab -e -u ice */10 * * * * sudo /home/ice/scripts/monitoring/temp.sh >> /home/ice/scripts/monitoring/temp.log 2>&1
Проверить что запуски происходят можно командой:
grep CRON /var/log/syslog
И еще одно — что бы логи не накапливались я настроил их ротацию. Что бы это сделать установим Logrotate
sudo apt-get install logrotate
А далее создадим в папке /etc/logrotate.d/ файл конфигурации. Мой выглядит так:
/home/ice/scripts/monitoring/temp.log { # путь к логам daily # ротировать ежедневно missingok # отсутствие файла не является ошибкой rotate 30 # сохраняется последние 30 ротированных файлов compress # сжимать ротируемый файл delaycompress # сжимать предыдущий файл при следующей ротации (т.е. файл *.log.1 будет не сжат, а *.log.2 и далее сжатыми) notifempty # не обрабатывать пустые файлы create 640 ice ice # сразу после ротации создать пустой файл с заданными правами и пользователем }
-
Другие мелочи
- htop — продвинутый монитор процессов
- пакет для измерения производительности системы, детали тут sysstat, а настройка тут — Permanent link to How to configure sysstat/sar on Ubuntu/Debian
- lynis — утилита, помогающая побороть желание «нужно больше контроля и мониторинга над системой», описание — lynis
- rtorrent — консольный торрент-клиент (я кстати еще и web-морду к нему пристроил, очень удобно), детали настройки можно найти тут — Установка rtorent+rutorrent на Debian/Ubuntu
- exim4 — почтовый сервер, конфигурация с использованием GMail SMTP описана тут — Configuring exim4 in Ubuntu to use GMail for SMTP
- proftpd — FTP сервер (настройку подсмотрел тут Настройка домашнего сервера на базе Debian)
- samba — сетевая файловая система (попробовать хотелось всего, вот и поставил), настройку можно найти тут — Установка и настройка Samba в Debian GNU/Linux и Ubuntu Linux
Для доступа samba использует системных пользователей, добавить их в базу данных SMB можно командойsmbpasswd -a ice
- mc — полезный файловый менеджер
- ssh — тут без комментариев
- в опции монтирования (/etc/fstab) добавил commit=60 для борьбы с излишним журналированием которое постоянно мучило жесткий диск (процесс jbd2)
Dev Environment
Итак, теперь самое интересное, что же мне удалось впихать в эту маленькую коробочку.
LAMP | nginx | Node.js | MongoDB | GIT | Java | Python | Ruby | .NET | Jenkins
LAMP
Да, я активный web-разработчик и без этой платформы как без рук. Ставится все элементарно:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install apache2 apache2-doc php5 libapache2-mod-php5 php-pear
sudo apt-get install mysql-server mysql-client php5-mysql
sudo apt-get install php5-curl php5-gd php5-imagick php5-ldap php5-imap php5-memcache php5-common php5-mysql php5-ps php5-tidy imagemagick php5-xcache php5-xdebug php5-xmlrpc php5-xsl
Но сразу после установки меня постигла неудача — php файлы никак не хотели обрабатываться apache'м. Для того что бы это исправить я произвел следующие манипуляции:
/etc/apache2$ sudo gedit apache2.con
# перед секцией инклудов добавил
AddHandler application/x-httpd-php .php .php4 .php3 .html
AddType application/x-httpd-php .html
Для удобного дебага php я поставил и настроил xdebug. Установка детально описана по следующим ссылкам:
— Configuring Xdebug for PHP development/Linux
— Remote Xdebug на PhpStorm
При создании виртуальных хостов не забываем прописывать их в hosts
nginx
Для повышение производительности апача рекомендуют использовать его в связке с nginx со следующим распределением ролей: apache — backend, nginx — frontend. О том как выполнить такую конфигурацию повествует статья — Установка и настройка Nginx. Nginx frontend + Apache backend.
Node.js
Прекрасная платформа, особенно для создания небольших клиент-серверных приложений. Одни только web-sockets чего стоят. Ну да ладно, вернемся к установке. Ставить node.js немного не тривиально, но не сложно — true'шным образом, то есть из исходников:
sudo apt-get install python g++ make checkinstall
mkdir ~/src && cd $_
wget -N http://nodejs.org/dist/node-latest.tar.gz
tar xzvf node-latest.tar.gz && cd node-v* # убираем "v" из номера версии в окне диалога
./configure
checkinstall
sudo dpkg -i node_*
Чуть более подробно установка расписана тут — Installing Node.js
MongoDB
А почему бы еще и не приобщиться к NoSQL сообществу? Вот и я задался этим вопросом. Ну может плотно NoSQL использовать я и не планировал, но пощупать — почему нет?
Устанавливаем!
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/debian-sysvinit dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
sudo apt-get update
sudo apt-get install mongodb-10gen
… и запускаем
sudo /etc/init.d/mongodb start
GIT
Давно уже хотелось съехать с публичных репозиториев на github. И вот пришло время. Git поставить не сложно, он в репозитории пакетов так и зовется — git, но сконфигурировать его для удобной работы немного сложнее, нам нужно:
— создать отдельного пользователя — git
— установить giolite для администрирования репозиториев
Вот это видео помогло побороть ситуацию когда мои ключи сгенерированные в putty игнорировались — How To Fix «Server Refused Our Key» Error That Caused By RSA Public Key Generated By Puttygen
Далее клонируем giolite репозиторий — ssh://git@192.168.1.110:/gitolite-admin.git и вуаля, управляем репами.
Настроить git+gitolite помогли следующие ссылки:
— Настройка сервера. Gitolite — хостинг git-репозиториев
— Собственный git-сервер с нуля
Для удобного обзора репозиториев из браузера существует — gitweb. Как его установить описано здесь — Setting up Gitweb on Debian.
От себя добавлю:
usermod -a -G gitolite www-data
для того что бы apach и gitolite подружились.
<VirtualHost *:81>
ServerAdmin webmaster@localhost
ServerName git-web.loc
SetEnv GITWEB_CONFIG /etc/gitweb.conf
DocumentRoot /home/git/repositories
Alias /static/gitweb.css /usr/share/gitweb/static/gitweb.css
Alias /static/git-logo.png /usr/share/gitweb/static/git-logo.png
Alias /static/git-favicon.png /usr/share/gitweb/static/git-favicon.png
Alias /static/gitweb.js /usr/share/gitweb/static/gitweb.js
Alias /git /home/git/repositories
ScriptAlias /gitweb.cgi /usr/lib/cgi-bin/gitweb.cgi
DirectoryIndex gitweb.cgi
<Directory /home/git/repositories/>
Allow from All
Options +ExecCGI
AllowOverride All
AuthType Basic
AuthName "Private Repository"
AuthUserFile /home/ice/stuff/keys/.htpasswd-gitweb
Require valid-user
AddHandler cgi-script .cgi
DirectoryIndex gitweb.cgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.* /gitweb.cgi/$0 [L,PT]
</Directory>
SetEnv GIT_PROJECT_ROOT /home/git/repositories
SetEnv GIT_HTTP_EXPORT_ALL
ErrorLog ${APACHE_LOG_DIR}/git_web_error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/git_web_access.log combined
</VirtualHost>
Basic авторизация по вкусу, можно отключить.
Java
Перейдем к java платформе. Первым делом удалим openjdk и поставим Java 7
sudo apt-get remove openjdk*
su -
# добавим репозитории java
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886
apt-get update
# принимаем лицензию Oracle software license
echo oracle-java7-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections
# ставим Oracle JDK7
apt-get install oracle-java7-installer
# выходим из под root
exit
# убедимся что java поставилась
java -version
Сверху я прибавил следующее ПО:
— scala (как раз изучаю, почему бы не потренироваться на своем сервере)
— glassfish — один из самых активно разрабатываемых (если не самый) серверов приложений
* если glassfish не запускается из-за того что занят порт 8080 (как это получилось у меня), то давайте сменим дефолтный порт. Для этого в GlassFish_Serverglassfishdomainsdomain1config находим наш порт и ставим другой:
<network-listener name="http-listener-1" port="8081" protocol="http-listener-1" thread-pool="http-thread-pool" transport="tcp"</network-listener>
Python
Следующим пожаловал питон вместе с django. Ставятся из репозитория довольно легко. Вот тут можно посмотреть на простоту использования — Writing your first Django app
Ruby
Как и питон, руби я поставил тоже со своим фреймворком — Rails. Ставить чуть сложнее, поэтому приводу инструкцию:
apt-get install build-essential libapache2-mod-passenger ruby rdoc ruby-dev libopenssl-ruby rubygems
gem install fastthread
gem install rails --version 3.0.4
А так же не забудьте добавить rails в $PATH:
PATH=".../var/lib/gems/VERSION/bin"
Ну а использовать все так же легко — Getting Started with Rails
Для внутренних нужд так же было решено развернуть баг-трекер, и им стал -Redmine.
Ставить вот так:
# доставляем нужные библиотеки
aptitude install libmagickcode-dev
aptitude install libmagickwand-dev
aptitude install ruby1.9.1-dev
aptitude install libmysqlclient-dev
# скачиваем и распаковываем redmine
cd /opt
wget http://files.rubyforge.vm.bytemark.co.uk/redmine/redmine-2.3.1.tar.gz
tar -zxvf redmine-2.3.1.tar.gz
cd /var/www
ln -s /redmine-2.3.1/public redmine
chown -R www-data:www-data /opt/redmine-2.3.1
Заходим в mysql клиент и создаем базу и пользователя:
CREATE DATABASE redmine_default CHARACTER SET utf8;
CREATE USER 'redmine'@'localhost' IDENTIFIED BY 'my-password';
GRANT ALL PRIVILEGES ON redmine_default.* TO 'redmine'@'localhost';
Создаем конфигурацию базы
cd /redmine-2.3.1/config
cp database.yml.example database.yml
vi database.yml
и заполняем ее
production:
adapter: mysql2
database: redmine_default
host: localhost
username: redmine
password: my-password
encoding: utf8
Создаем файл настроек:
cd /redmine-2.3.1/config
cp configuration.yml.example configuration.yml
vi configuration.yml
и настраиваемся (благо в конфиге полно комментариев).
Теперь ставим ruby bundle
gem install bundler
bundle install --without development test postgresql sqlite
rake generate_secret_token
bundle install
и готовим базу данных:
RAILS_ENV=production rake db:migrate
RAILS_ENV=production rake redmine:load_default_data
После всего этого нужно настроить виртуальных хост в апаче и можно пользоваться.
Настройка (получение информации о комитах из репозитория) описана тут — Redmine Settings. С выбрал вариант в котором с помощью Cron настраивается автоматический опрос репозиториев.
.NET
Не забываем про .NET платформу. Основные компоненты это собственно mono платформа и XSP (ASP.NET сервер) ставятся вот так:
sudo apt-get install mono-common mono-xsp4
Все, теперь почти все прелести .NET нам доступны.
Деталей можно почерпнуть тут: Mono for Debian .
Jenkins
А венчает все это — CI сервер. Давайте рассмотрим как его поставить и настроить например для… PHP:
Ставим Jenkins
sudo apt-get update
sudo apt-get install php5-cli php5-xdebug php-pear ant git
php -r 'echo "Xdebug loaded? "; echo (extension_loaded("xdebug")) ? "yes" : "no"; echo chr(10);'
wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo bash -c "echo 'deb http://pkg.jenkins-ci.org/debian binary/' > /etc/apt/sources.list.d/jenkins.list"
sudo apt-get update
sudo apt-get install jenkins
wget http://localhost:8080/jnlpJars/jenkins-cli.jar
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin checkstyle
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin cloverphp
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin dry
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin htmlpublisher
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin jdepend
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin plot
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin pmd
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin violations
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin xunit
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin git
java -jar jenkins-cli.jar -s http://localhost:8080 safe-restart
sudo pear upgrade PEAR
sudo pear channel-discover pear.pdepend.org
sudo pear channel-discover pear.phpmd.org
sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover components.ez.no
sudo pear channel-discover pear.symfony-project.com
sudo pear install pdepend/PHP_Depend
sudo pear install phpmd/PHP_PMD
sudo pear install phpunit/phpcpd
sudo pear install phpunit/phploc
sudo pear install PHPDocumentor
sudo pear install PHP_CodeSniffer
sudo pear install --alldeps phpunit/PHP_CodeBrowser
sudo pear install --alldeps phpunit/PHPUnit
Конфигурируем:
— скачиваем /build.xml из http://jenkins-php.org/ и редактируем под свой проект
— качаем PMD правила http://phpmd.org/ и кладем как /build/phpmd.xml в проект
— опционально можно добавить ее правил http://pear.php.net/ и ложим как /build/phpcs.xml в проект
— конфигурируем PHPUnit в /tests/phpunit.xml
— скачиваем шаблон задания
cd /var/lib/jenkins/jobs/
sudo git clone git://github.com/sebastianbergmann/php-jenkins-template.git php-template
sudo chown -R jenkins:nogroup php-template/
sudo /etc/init.d/jenkins stop
sudo /etc/init.d/jenkins start
— создаем новое задание из шаблона, привязываем к репозиторию (возможно придется добавить плагин под свою систему контроля версий) и радуемся.
Резервное копирование
Понятное дело что избежать поломок оборудования нельзя, но совсем другие ощущения возникают при этой мысли когда у тебя есть резервная копия данных (да еще и свежая).
Сам процесс разделен на 2 вида:
— полное (делаю выборочно, когда чувствую что в системе прошло много изменений и нужно бы сохраниться)
— частичное (все узлы системы которые подвержены ежедневным изменениям: базы, исходники и т.д.)
Сбор полного дампа произвожу с помощью remastersys скриптом.
#!/bin/bash
# замеряем сколько идет резервирование
start=`date +%s`
echo '[FULL BACK UP Start]'
DATE_NOW=`date +%F`
echo '[FULL BACK UP Dump Creation]'
# запускаем резервирование
sudo remastersys backup install-$DATE_NOW.iso
echo '[FULL BACK UP Dump Saving]'
# перемещаем в основную папку хранения
sudo cp /home/remastersys/remastersys/install-$DATE_NOW.iso /home/backups/system-iso/install-$DATE_NOW.iso
sudo cp /home/remastersys/remastersys/install-$DATE_NOW.iso.md5 /home/backups/system-iso/install-$DATE_NOW.iso.md5
echo '[FULL BACK UP Clean up]'
# чистим tmp
sudo remastersys clean
echo '[FULL BACK UP End]'
end=`date +%s`
runtime=$((end-start))
echo 'Backup time =' $runtime 'sec(s)'
Частичное выполняется скрпитом в cron еженощно.
#!/bin/bash
start=`date +%s`
echo '[BACK UP Start]'
DATE_PREF=`date +%F`
echo '[BACK UP Config]'
# настраиваем пути к папкам
BACKUP_MYSQL_DIR=/home/backups/mysql/$DATE_PREF
BACKUP_WWW_DIR=/home/backups/www/$DATE_PREF
BACKUP_GIT_DIR=/home/backups/git/$DATE_PREF
echo '[BACK UP Clean up]'
# чистим все что лежит дольше недели
find /home/backups/mysql/ -mtime +7 -print -mindepth 1 -delete >/dev/null 2>&1
find /home/backups/www/ -mtime +7 -print -mindepth 1 -delete >/dev/null 2>&1
find /home/backups/git/ -mtime +7 -print -mindepth 1 -delete >/dev/null 2>&1
echo '[BACK UP Not Clened Items]'
ls /home/backups/mysql/
ls /home/backups/www/
ls /home/backups/git/
echo '[BACK UP Back Up Hosts]'
# резервируем хосты
tar cpzf $BACKUP_WWW_DIR-www.tgz /home/www/ >/dev/null 2>&1
echo '[BACK UP Back Up Repositories]'
# резервируем репозитории
tar cpzf $BACKUP_GIT_DIR-git.tgz /home/git/ >/dev/null 2>&1
echo '[BACK UP Back Up MySQL]'
# резервируем базы данных
mysqldump -q -u root -p<password> -h localhost tt_rss | gzip -c > $BACKUP_MYSQL_DIR-tt_rss.sql.gz
mysqldump -q -u root -p<password> -h localhost test | gzip -c > $BACKUP_MYSQL_DIR-test.sql.gz
mysqldump -q -u root -p<password> -h localhost redmine | gzip -c > $BACKUP_MYSQL_DIR-redmine.sql.gz
mysqldump -q -u root -p<password> -h localhost phpmyadmin | gzip -c > $BACKUP_MYSQL_DIR-phpmyadmin.sql.gz
mysqldump -q -u root -p<password> --skip-lock-tables -h localhost performance_schema | gzip -c > $BACKUP_MYSQL_DIR-performance_schema.sql.gz
mysqldump -q -u root -p<password> --skip-lock-tables -h localhost information_schema | gzip -c > $BACKUP_MYSQL_DIR-information_schema.sql.gz
mysqldump -q -u root -p<password> --events -h localhost mysql | gzip -c > $BACKUP_MYSQL_DIR-mysql.sql.gz
echo '[BACK UP New Items]'
ls /home/backups/mysql/ | grep $DATE_PREF
ls /home/backups/www/ | grep $DATE_PREF
ls /home/backups/git/ | grep $DATE_PREF
echo '[BACK UP End]'
end=`date +%s`
runtime=$((end-start))
echo 'Backup time =' $runtime 'sec(s)'
echo '========================================================='
Как видно — храню последние 7 копий.
Спасибо! Надеюсь было интересно!
P.S. В случае возникновения вопросов — буду рад помочь.
P.P.S. Дайте, инвайт, пожалуйста.
Автор: atamur