RTMP сервер на Debian Linux

Установка

Затем устанавливаем дополнительные пакеты:

apt-get update
apt-get install java-package
apt-get install sun-java6-jdk
apt-get install sun-java6-jre
apt-get install ant

Установка Red5

wget https://github.com/Red5/red5-server/releases/download/v1.0.8-M13/red5-server-1.0.8-M13.tar.gz
tar xvfz red5-server-1.0.8-M13.tar.gz
mv red5-server-1.0.8-M13 red5
mv red5 /usr/share/

Запускаем:

cd /usr/share/red5
sh red5.sh

В результате увидим работающий сервер Red5 по адресу: http://localhost:5080

Если работает firewall, то добавляем порты:

ACCEPT tcp -- anywhere anywhere tcp dpt:1935 
ACCEPT tcp -- anywhere anywhere tcp dpt:5080 
ACCEPT tcp -- anywhere anywhere tcp dpt:omniorb 
ACCEPT tcp -- anywhere anywhere tcp dpt:8443

В качестве плеера советую как вариант использовать video.js.

RainbowCrack

rainbowcrack

Собрал на днях полигон для прогона RainbowCrack «тестов».

Пока доступны алгоритмы: SHA1, MD5

Таблицы:

md5_mixalpha-numeric#1-8
(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789)
Вероятность подбора: 99.9%
127GB

md5_mixalpha-numeric#1-9
(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789)
Вероятность подбора: 96.8%
1009GB

md5_mixalpha-numeric-all-space#1-8
(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 )
Вероятность подбора: 99.9%
1049GB

sha1_mixalpha-numeric#1-8
(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789)
Вероятность подбора: 99.9%
127GB

sha1_mixalpha-numeric#1-9
(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789)
Вероятность подбора: 96.8%
690GB

 

Конфигурация железа в данной генерации:

Core i7 4790 CPU (rcrack)
2 x GeForce GTX 680 GPU (rcrack_cuda)
4 x Seagate ST2000DM001 собраны в RAID 0
4GB DDR3

Основной просчет ведется на 2-х GPU, но для тестов производительности доступен также вариант с прогоном на CPU.

 

Производительность для 1 хэша

В текущей конфигурации скорость вычислений доходит до:

8.96E+12 (Plaintexts per Second) на 2-х GPU GeForce GTX 680

9.21E+11 (Plaintexts per Second) при использовании CPU i7 4790.

Открыт ограниченный бесплатный 🙂 доступ по адресу: http://891rpm.arthead.ru/rc/

0. [2016-01-20] Доступ предоставляется по запросу на странице сервиса.
1. [2016-01-20] Введено ограничение на количество одновременных запусков тестов.
2. [2016-01-26] Введено ограничение на обращение к сервису с одного IP.

В планах:

0. Добавить кириллицу в таблицы
1. Добавить алгоритмы RIPEMD-160 и MySQL SHA1

P.S. Front-End для сервиса (для своей тренировки) написан на Django.
Позже выложу исходники 🙂

Визуальное распознавание хэшей

john-to-crack-the-password

13-символьный хэш:

DES (UNIX)

FkL6hgPZ138Ug
EZUv/lAcqf06.

 

16-символьный хэш:

MySQL

29bad1457ee5e49e​

 

32-символьные хэши:

без соли: md5 или md5($md5)

1a1dc91c907325c69271ddf0c944bc72​

с солью 2 символа: md5($salt.$pass)

bbde0359d80a56c0765bf30e3116c73d:b0​

с солью 3,30 символов: md5(md5($pass).$salt)

9069b0a70e89821710c7b9c6ddfa1339:*|/
33962b23840f5212ff5f594c3dea1b5a:VhVpcK>xIzU=JYi&|7wje4MWyBF$?#​

с солью 5,8 символов: md5(md5($salt).md5($pass))

8ca78a583e1b35e175ec5bd02e880e35:gEA_Z
66cea44067b962a71d9f578363aae68c:mQHJedIM

с солью 16,32 символа: md5($pass.$salt)

a382a8e7d694cb4fc71d8cda67ee0802:HgtalJ4UaxuSBwSX
d666f494d2ea2bd1819a3ca2e9409f36:LCyAwlMKplHxkFp6SZSfNlnLdBTrOcG6​

 

40-символьные хэши:

MySQL 5

признак: верхний регистр символов

root:*94BDCEBE19083CE2A1F959FD02F964C7Af4CfC29
*32FD2FB910CC84D8E710B431E1C208514F56D9EF
7F44978F28CCD7874293693FD73F4BDDD64321E1

SHA-1

признак: нижний регистр символов

9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684

​SHA1($username.$pass)

признак: наличие 4-символьной соли, обязательно наличие имени пользователя (username)

user:45f106ef4d5161e7aa38cf6c666607f25748b6ca:bf76

 

Другие хэши:

MD5 (UNIX)

признак: наличие $1$ в начале хэша

$1$dNSCl38g$f0hqUX9K7lr3hFzU4JspZ0

MD5 (WordPress)

признак: наличие $P$B или $P$9 в начале хэша

$P$BHUnawZ54ZdpoZOm4sbVAK0

MD5 (PHPBB3)

признак: наличие $H$7 или $H$9 в начале хэша

$H$9x9g17Renn7Nk1l8MG64nD1

​MD5 (APR)

признак: наличие $apr1$ в начале хэша

$apr1$$kRqAZHnuzcwDL84Mm7oc1.

​OpenBSD Blowfish

признак: наличие $2a$ в начале хэша

$2a$08$Pv6/4g5LwwisUCJmim/tR.CT7vXfUYjsSqDfZ/YU.1urjzNmQFQum

SHA-256 (UNIX)

признак: наличие $5$ в начале хэша

$5$1$6rPISQo58O3bm0PRwPmc3uhLi.TPE1NhHq0VIVf1X/8​

SHA-512 (UNIX)

признак: наличие $6$ в начале хэша

$6$1$RRbbJXv8x38tKhWFDQ3m9bE1L/2yteMGAJ7E6h1OMqhpFDO3EHUvv3YD0oX0NywDa.toXreflU/VBJ2dwKTyM0

Adding ES7 Class Properties to an ES6 React Component

ECMAScript 6

I’ve been investigating React and Flux over the last three posts, but one thing really didn’t sit right with me. That one thing is the React PropTypes in an ES6 class. I had to do something like this:

import React from 'react';
 
class NavBrand extends React.Component {
  render() {
    return(<h1>{this.props.title}</h1>});
  }
}
 
NavBrand.propTypes = {
  title: React.PropTypes.string.isRequired
};
 
export default NavBrand

It’s ES6 code, but the fact that I have to munge the class after it has been created did not sit well. I wanted the propTypes to be a part of the class – just like a class in just about every other language.

Fortunately, there is a current proposal for class properties in ES7 (or ES2016 or ES vNext). It’s not ratified yet and the proposal may change. The ES6 version (above) is ratified and perfectly valid code. Let’s look at what the alternate ES7 version would look like:

import React from 'react';
 
export default class NavBrand extends React.Component {
  static propTypes = {
    title: React.PropTypes.string.isRequired
  };
 
  render() {
    return (<h1>{this.props.title}</h1>);
  }
}

I like the aesthetics of this version much more than the ES6 version. The propTypes is in the right place.

The bad news: This doesn’t lint and it doesn’t compile.
The good news: We can fix that!

Linting

I use eslint for my linter. You can change the parser that eslint uses so that it uses babel just like the compiler stage. Anything that would go through the compiler will go through the linter as well. To do this I need another package –babel-eslint:

npm install --save-dev babel-eslint

Then I need to adjust my .eslintrc file to use the new parser:

"parser": "babel-eslint",
"plugins": [
  "react"
],

Linting will pass if you run eslint on that JSX file, or if you run gulp eslint from my tutorial code. If you introduce an error (say, removing the semi-color from the return statement), eslint will still catch that.

Transpiling

To fix the transpiling, I need to make changes to my task. Here is the new task:

var babelify = require('babelify'),
    browserify = require('browserify'),
    gulp = require('gulp'),
    rename = require('gulp-rename'),
    source = require('vinyl-source-stream');
 
var config = {
    dest: './wwwroot'
};
 
var files = {
    entry: './app.jsx'
};
 
gulp.task('bundle', ['eslint'], function () {
    var bundler = browserify({
        extensions: ['.js', '.jsx'],
        transform: [babelify.configure({
          optional: [ "es7.classProperties" ]
        })],
        debug: true // produce source maps
    });
 
    return bundler.add(files.entry)
        .bundle()
        .pipe(source(files.entry))
        .pipe(rename('bundle.js'))
        .pipe(gulp.dest(config.dest));
});

Of course, you will put the requires at the top of your gulp file, and have extra stuff in the config and files objects. However, the task itself works. Note that I need to configure babelify to add in an optional configuration list that enables es7.classProperties. If your code uses one of the other optional experimental features, you can list those too.

Thanks to this, I can now convert all my React components to use the ES7 class properties syntax. I hope this proposal makes it in.

http://shellmonger.com/2015/08/21/adding-es7-class-properties-to-an-es6-react-component/

Настройка разрешения экрана в Linux

linux-resolution1. Используем cvt для вычисления параметров, которые будем использовать в xrandr:

cvt 2560 1440

Пример:

# 2560x1440 59.96 Hz (CVT 3.69M9) hsync: 89.52 kHz; pclk: 312.25 MHz
Modeline "2560x1440_60.00" 312.25 2560 2752 3024 3488 1440 1443 1448 1493 -hsync +vsync

 

2. Используем параметры cvt в xrandr:

xrandr --newmode "2560x1440" 312.25 2560 2752 3024 3488 1440 1443 1448 1493 -Hsync +Vsync

(Параметры Hsync и Vsync должны начинаться с заглавных букв).

 

3. Добавляем новый режим «2560×1440» в xrandr:

xrandr --addmode Virtual1 "2560x1440"

(Можно заменить Virtual1 на то, что нужно… Посмотреть можно командой xrandr)

 

4. Включить новый режим:

xrandr --output Virtual1 --mode "2560x1440"

 

WGET. Лучшие практики использования

wget

Загрузка всех URL, указанных в файле FILE:

$ wget -i FILE

Скачивание файла в указанный каталог (-P):

$ wget -P /path/for/save ftp://ftp.example.org/some_file.iso

Использование имя пользователя и пароля на FTP/HTTP:

$ wget ftp://login:password@ftp.example.org/some_file.iso
$ wget --user=login --password=password ftp://ftp.example.org/some_file.iso

Скачивание в фоновом режиме (-b):

$ wget -b ftp://ftp.example.org/some_file.iso

Продолжить (-c continue) загрузку ранее не полностью загруженного файла:

$ wget -c http://example.org/file.iso

Скачать страницу с глубиной следования 10, записывая протокол в файл log:

$ wget -r -l 10 http://example.org/ -o log

Скачать содержимое каталога http://example.org/~luzer/my-archive/ и всех его подкаталогов, при этом не поднимаясь по иерархии каталогов выше:

$ wget -r --no-parent http://example.org/~luzer/my-archive/

Для того, чтобы во всех скачанных страницах ссылки преобразовывались в относительные для локального просмотра, необходимо использовать ключ -k:

$ wget -r -l 10 -k http://example.org/

Также поддерживается идентификация на сервере:

$ wget --save-cookies cookies.txt \
  --post-data 'user=foo&password=bar' \
  http://example.org/auth.php

Скопировать весь сайт целиком:

$ wget -r -l 0 -k http://example.org/

Скачивание галереи картинок с превьюшками.

$ wget -r -k -p -l1 -I /images/ -I /thumb/ \
  --execute robots=off www.example.com/gallery.html

Сохранить веб страницу (как она открывается локально) в текущую директорию

$ (cd cli && wget -nd -pHEKk http://www.pixelbeat.org/cmdline.html)

Продолжить скачивание частично скаченного файла

$ wget -c http://www.example.com/large.file

Скачать множество файлов в текущую директорию

$ wget -r -nd -np -l1 -A '*.jpg' http://www.example.com/

Отображать вывод напрямую (на экран)

$ wget -q -O- http://www.pixelbeat.org/timeline.html | grep 'a href' | head

Скачать url в 01:00 в текущую директорию

$ echo 'wget url' | at 01:00

Сделать закачку с уменьшенной скоростью В данном случае 20 КB/s

$ wget --limit-rate=20k url

Проверить ссылки в файле

$ wget -nv --spider --force-html -i bookmarks.html

Оперативно обновлять локальную копию сайта (удобно использовать с cron)

$ wget --mirror http://www.example.com/

Используем wildcard для того чтобы скачать несколько страниц

$ wget http://site.com/?thread={1..100}
$ wget http://site.com/files/main.{css,js}

Запустить скачивание списка ссылок в 5 потоков

$ cat links.txt | xargs -P 5 wget {}

Проверить ссылки из файла на живость

$ cat list.txt
http://yandex.ru
http://google.ru
http://yandex.ru/qweqweqweqwe
$ wget -nv  --spider -i list.txt
2013-08-08 22:40:20 URL: http://www.yandex.ru/ 200 Ok
2013-08-08 22:40:20 URL: http://www.google.ru/ 200 OK
http://yandex.ru/qweqweqweqwe:
Удалённый файл не существует — битая ссылка!

Источники:

How To Install Grub Customizer 4.0.6 On Debian 8.0 Jessie

grub2Hello Linux Geeksters. As you may know, Grub Customizer is a nice application, that allows the user to edit the menu entries from the GRUB booting screen, set the default operating system, change the installed OS via a livecd.

The latest version available is Grub Customizer 4.0.6, which has has been released a while ago, bringing fixes.

In this article I will show you how to install Grub Customizer 4.0.6 on Debian 8.0 Jessie and derivative systems.

Because it is not available via repository, we have to download the deb packages from launchpad and install the via command-line. I prefer gdebi over dpkg due to the fact that it also handles dependencies.

Follow the instructions for your system’s architecture exactly, in order to get a successful installation.

How to install Grub Customizer 4.0.6 on 32 bit Debian 8.0 systems:

$ sudo apt-get install gdebi
$ wget "https://launchpad.net/~danielrichter2007/+archive/ubuntu/grub-customizer/+files/grub-customizer_4.0.6-0ubuntu1%7Eppa1p_i386.deb" -O grub-customizer_4.0.6_i386.deb
$ sudo gdebi grub-customizer_4.0.6_i386.deb

How to install Grub Customizer 4.0.6 on 64 bit Debian 8.0 systems:

$ sudo apt-get install gdebi
$ wget "https://launchpad.net/~danielrichter2007/+archive/ubuntu/grub-customizer/+files/grub-customizer_4.0.6-0ubuntu1%7Eppa1p_amd64.deb" -O grub-customizer_4.0.6_amd64.deb
$ sudo gdebi grub-customizer_4.0.6_amd64.deb

Optional, to remove grub-customizer, do:

$ sudo apt-get remove grub-customizer

 

Simplifying your Django Frontend Tasks with Grunt

grunt-logoGrunt is a powerful task runner with an amazing assortment of plugins. It’s not limited to the frontend, but there are many frontend-oriented plugins that you can take advantage of to combine and minify your static media, compile sass and less files, watch for changes during development and reload your browser automatically, and much more.

In the last several years, the amount of tooling around frontend development has expanded dramatically. Frameworks, libraries, preprocessors and postprocessors, transpilers, template languages, module systems, and more! Wiring everything together has become a significant challenge, and a variety of build tools have emerged to help ease this burden. Grunt is the current leader because of its fantastic plugin community, and it contains a wide array of plugins that can be very valuable to a Django developer. Today I’m going to talk about an easy way to integrate Grunt with Django’s runserver, and highlight a few plugins to handle common frontend tasks that Django developers often deal with.

Installing Grunt

Grunt uses Node.js, so you’ll need to have that installed and configured on your system. This process will vary depending on your platform, but once it’s done you’ll need to install Grunt. From the documentation:

$ npm install -g grunt-cli

 

This will put the grunt command in your system path, allowing it to be run from any directory.

Note that installing grunt-cli does not install the Grunt task runner! The job of the Grunt CLI is simple: run the version of Grunt which has been installed next to a Gruntfile. This allows multiple versions of Grunt to be installed on the same machine simultaneously.

Next, you’ll want to install the Grunt task runner locally, along with a few plugins that I’ll demonstrate:

$ npm install --save-dev grunt grunt-contrib-concat grunt-contrib-uglify grunt-sass grunt-contrib-less grunt-contrib-watch

 

Managing Grunt with runserver

There are a few different ways to get Grunt running alongside Django on your local development environment. The method I’ll focus on here is by extending the runserver command. To do this, create a gruntserver command inside one of your project’s apps. I commonly have a «core» app that I use for things like this. Create the «management/command» folders in your «myproject/apps/core/» directory (adjusting that path to your own preferred structure), and make sure to drop an __init__.py in both of them. Then create a «gruntserver.py» inside «command» to extend the built-in.

In your new «gruntserver.py» extend the built-in and override a few methods so that you can automatically manage the Grunt process:

import os
import subprocess
import atexit
import signal

from django.conf import settings
from django.contrib.staticfiles.management.commands.runserver import Command\
    as StaticfilesRunserverCommand


class Command(StaticfilesRunserverCommand):

    def inner_run(self, *args, **options):
        self.start_grunt()
        return super(Command, self).inner_run(*args, **options)

    def start_grunt(self):
        self.stdout.write('>>> Starting grunt')
        self.grunt_process = subprocess.Popen(
            ['grunt --gruntfile={0}/Gruntfile.js --base=.'.format(settings.PROJECT_PATH)],
            shell=True,
            stdin=subprocess.PIPE,
            stdout=self.stdout,
            stderr=self.stderr,
        )

        self.stdout.write('>>> Grunt process on pid {0}'.format(self.grunt_process.pid))

        def kill_grunt_process(pid):
            self.stdout.write('>>> Closing grunt process')
            os.kill(pid, signal.SIGTERM)

        atexit.register(kill_grunt_process, self.grunt_process.pid)

 

A barebones grunt config

To get started with Grunt, you’ll need a barebones «Gruntfile.js» at the root of your project to serve as your config.

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    // Task configuration goes here.

  });

  // Load plugins here.
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-watch');

  // Register tasks here.
  grunt.registerTask('default', []);

};

 

Combining static media

A common task for the frontend, and one that we often use complex apps for in Django, is combining and minifying static media. This can all be handled by Grunt if you like, avoiding difficulties sometimes encountered when using an integrated Django app.

To combine files, use the concat plugin. Add some configuration to the «grunt.initConfig» call, using the name of the task as the key for the configuration data:

grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    // Task configuration goes here.

    concat: {
      app: {
        src: ['myproject/static/js/app/**/*.js'],
        dest: 'build/static/js/app.js'
      },
      vendor: {
        src: ['myproject/static/js/vendor/**/*.js'],
        dest: 'build/static/js/lib.js'
      }
    }
  });

 

This will combine all Javascript files under «myproject/static/app/js» into one file called «myproject/build/static/js/app.js». It will also combine all Javascript files under «myproject/static/vendor» into one file called «myproject/build/static/js/lib.js». You’ll likely want to refine this quite a bit to pick up only the files you want, and possibly build different bundles for different sections of your site. This will also work for CSS or any other type of file, though you may be using a preprocessor to combine your CSS and won’t need this.

You’ll probably want to use this along with the «watch» plugin for local development, but you’ll use the «uglify» plugin for deployment.

Minifying static media

Once your app is ready for production, you can use Grunt to minify the JavaScript with the uglify plugin. As with concatenation, minification of your CSS will likely be handled by your preprocessor.

This task should be run as part of your deploy process, or part of a pre-deploy build process. The uglify config will probably be very similar to your concat config:

uglify: {
    app: {
      files: {'build/static/js/app.min.js': ['myproject/static/js/app/**/*.js']}
    },
    vendor: {
      files: {'build/static/js/lib.min.js': ['myproject/static/js/vendor/**/*.js']}
    }
  }

 

The main difference is that uglify takes the new-style «files» option instead of the classic «src» and «dest» options that concat uses.

Compiling Sass

You can compile Sass with Compass using the compass plugin, but I prefer to use the speedier sass plugin that uses libsass. Here’s an example that includes the Foundation library:

sass: {
      dev: {
        options: {
          includePaths: ['bower_components/foundation/scss']
        },
        files: {
          'build/static/css/screen.css': 'myproject/static/scss/screen.scss'
        }
      },
      deploy: {
        options: {
          includePaths: ['bower_components/foundation/scss'],
          outputStyle: 'compressed'
        },
        files: {
          'build/static/css/screen.min.css': 'myproject/static/scss/screen.scss'
        }
      }
    },

 

Compiling Less

Less is compiled using the less plugin.

less: {
            dev: {
                options: {
                    paths: ['myproject/static/less']
                },
                files: {
                    'build/static/css/screen.css': 'myproject/static/less/screen.less'
                }
            }
            deploy: {
                options: {
                    paths: ['myproject/static/less'],
                    compress: true
                },
                files: {
                    'build/static/css/screen.min.css': 'myproject/static/less/screen.less'
                }
            }
        },

 

Watching for changes and live reloading

Now that you’ve got your initial operations configured, you can use the watch plugin to watch for changes and keep the files up to date. It also will send livereload signals, which you can use to automatically refresh your browser window.

watch: {
            options: {livereload: true}
            javascript: {
                files: ['myproject/static/js/app/**/*.js'],
                tasks: ['concat']
            },
            sass: {
                files: 'myproject/static/scss/**/*.scss',
                tasks: ['sass:dev']
            }
        }

 

Note the way the task is specified in the «sass» watch config. Calling «sass:dev» instructs it to use the «dev» config block from the «sass» task. Using «sass» by itself as the name of the task would have invoked both «sass:dev» and «sass:deploy» from our configuration above.

Also note how we’re using a top-level «options» definition here to make livereload the default. You can then override that for an individual watch definition if you don’t need livereload for that one.

In order for the browser to make use of the livereload signals, we’ll need to add a <script> tag that retrieves code from the livereload server that Grunt starts in the background. In Django, you’ll want to hide this tag behind a DEBUG check.

{% if debug %}
    <script src="//localhost:35729/livereload.js"></script>
{% endif %}

 

You can also use a LiveReload browser extension instead.

More to come

Grunt is a fantastic tool and one that makes it easier to work with the growing set of frontend tools that are emerging. There’s a vibrant plugin ecosystem, and its capabilities are growing all the time. I’ll be covering more of those tools in the future, and I’ll be sure to include Grunt configuration for each one. Enjoy!

Brandon Konkle

CGroups: Лимит на разделение ресурсов, а не на ограничение

Linux_kernel_unified_hierarchy_cgroups_and_systemd.svg

В отличие от CentOS у Debian 7 Wheezy фактически нет нормального мейнтенера подсистемы cgroups, поэтому обойтись установкой пары пакетов и правкой 1-2х конфигов не получится.

apt-get install -y cgroup-bin libcgroup1

 

Копируем примеры конфигов:

cp /usr/share/doc/cgroup-bin/examples/cgconfig.conf /etc/cgconfig.conf
cp /usr/share/doc/cgroup-bin/examples/cgconfig.sysconfig /etc/default/cgconfig
zcat /usr/share/doc/cgroup-bin/examples/cgconfig.gz > /etc/init.d/cgconfig
chmod +x /etc/init.d/cgconfig

 

Создаем спец-папку (без нее поймаем ошибку «touch: cannot touch /var/lock/subsys/cgconfig: No such file or directory [FAIL] Failed to touch /var/lock/subsys/cgconfig … failed!»):

mkdir -p /var/lock/subsys

 

Теперь добавляем cgroup для тестов, пусть это будет cpuacct, так как она не приводит к деградациям и ее можно использовать безвредно и на боевом ПО.

Добавляем в конфиг: /etc/cgconfig.conf следующие строки:

mount {
cpuacct = /mnt/cgroups/cpuacct;
}
group wwwdata {
cpuacct {
}
}

 

Теперь попробуем стартануть его:

/etc/init.d/cgconfig restart

 

Убеждаемся, что cgroup была корректно смонтирована:

cat /proc/mounts |grep cgroup
cgroup /mnt/cgroups/cpuacct cgroup rw,relatime,cpuacct 0 0

 

А сама папка выглядит примерно так:

ls -al /mnt/cgroups/cpuacct/
total 4.0K
drwxr-xr-x. 3 root root 0 Feb 5 14:04 .drwxr-xr-x. 3 root root 4.0K Feb 5 14:04 ..-rw-r--r--. 1 root root 0 Feb 5 14:04 cgroup.clone_children
--w--w--w-. 1 root root 0 Feb 5 14:04 cgroup.event_control
-rw-r--r--. 1 root root 0 Feb 5 14:04 cgroup.procs
-r--r--r--. 1 root root 0 Feb 5 14:04 cpuacct.stat
-rw-r--r--. 1 root root 0 Feb 5 14:04 cpuacct.usage
-r--r--r--. 1 root root 0 Feb 5 14:04 cpuacct.usage_percpu
-rw-r--r--. 1 root root 0 Feb 5 14:04 notify_on_release
-rw-r--r--. 1 root root 0 Feb 5 14:04 release_agent
-rw-r--r--. 1 root root 0 Feb 5 14:04 tasks
drwxr-xr-x. 2 root root 0 Feb 5 14:04 wwwdata

 

Теперь нам нужно добиться того, чтобы процессы конкретного пользователя загонялись в определенную cgroup.

Снова копируем конфиги:

cp /usr/share/doc/cgroup-bin/examples/cgrules.conf /etc/cgrules.conf
cp /usr/share/doc/cgroup-bin/examples/cgred /etc/init.d/cgred
cp /usr/share/doc/cgroup-bin/examples/cgred.conf /etc/default/cgred.conf
chmod +x /etc/init.d/cgred

 

Далее правим баги мейнтейнеров Debian:

sed -i 's/sysconfig/default/' /etc/init.d/cgconfig

 

Потом добавялем туда (/etc/cgrules.conf) одну строчку в самый низ:

@www-data cpuacct wwwdata/

 

Далее отключаем создание дефалт группы (в которую система будет помещать все процессы кроме тех, которые помещены в иные группы):

vim /etc/default/cgconfig
CREATE_DEFAULT=no

 

Таким образом мы настраиваем помещение всех процессов пользователя www-data в группу с именем wwwdata.

После этого несколько раз (потому что что-то в скриптах не то и с первого раза у него не выходит размонтировать cgroup) дергаем команду:

/etc/init.d/cgconfig stop

 

И потом запускаем:

/etc/init.d/cgconfig start

 

После этого настраиваем демона cgred, который, собственно, должен распихивать процессы по cgroup:

/etc/init.d/cgred start

 

Но нас постигнет ужасное разочарование — init скрипт тупо взят из RedHat без должной доработки под особенности Debian (впрочем, в /etc/init.d/cgconfig примерное тоже самое — там вместо /etc/default используется путь /etc/sysconfig):

/etc/init.d/cgred: line 43: /etc/rc.d/init.d/functions: No such file or directory
Starting CGroup Rules Engine Daemon: /etc/init.d/cgred: line 85: daemon: command not found

Чтобы исправить это открываем /etc/init.d/cgred и комментируем 43ю строку с кодом: «/etc/rc.d/init.d/functions».

Потом ищем строку

daemon --check $servicename --pidfile $pidfile $CGRED_BIN $OPTIONS

и заменяем на:

start-stop-daemon --start --quiet --pidfile $pidfile --exec $CGRED_BIN -- $OPTIONS

 

Далее правим:

sed -i 's/sysconfig/default/' /etc/init.d/cgred

 

Еще нужно исправить группу, от имени которой будет работать демон:

vim /etc/default/cgred.conf

 

и заменяем SOCKET_GROUP=»cgred» на SOCKET_GROUP=»»

Далее нам нужно создать папку для нашей cgroup:

mkdir /mnt/cgroups/cpuacct/wwwdata

 

Итак, запускаем демона:

/etc/init.d/cgred start

 

После этого нужно инициировать перезапуск процессов, которые нам интересно поместить в cgroup, в моем случае это nginx работающий от имени пользователя www-data:

/etc/init.d/nginx reload

 

Все, теперь убеждаемся, что процессы попали в нужную cgroup:

cat /mnt/cgroups/cpuacct/wwwdata/tasks
28623
28624
28625
28626